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/03/02 09:07:09 UTC

[isis] 01/01: ISIS-2444: updates some docs for security

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

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

commit 600de1432ea871b6eb3accefe6a83f757f153f12
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Mar 2 09:03:17 2021 +0000

    ISIS-2444: updates some docs for security
    
    Also moves Authenticator and Authorizor APIs up to their respective parent packages
---
 .../modules/_overview/pages/about.adoc             | 12 ++--
 .../index/services/bookmark/BookmarkHolder.adoc    | 18 ++++-
 .../BookmarkService_020-examples-and-usage.adoc    | 22 +++---
 .../interaction/session/InteractionFactory.adoc    |  6 +-
 .../security/authentication/Authentication.adoc    | 84 ++++++++++++++++++++++
 .../authentication/AuthenticationRequest.adoc      | 40 +++++++++++
 .../security/authentication/Authenticator.adoc     | 51 +++++++++++++
 .../index/security/authorization/Authorizor.adoc   | 40 +++++++++++
 .../shiro/IsisModuleExtSecmanShiroRealm.adoc       |  4 +-
 .../shiro/authentication/AuthenticatorShiro.adoc   |  2 +-
 .../index/shiro/authorization/AuthorizorShiro.adoc |  2 +-
 .../service/conneg/ContentNegotiationService.adoc  |  4 +-
 .../modules/btb/pages/hints-and-tips.adoc          |  3 +-
 .../pages/hints-and-tips/vetoing-visibility.adoc   | 26 +++++--
 .../applib/services/bookmark/BookmarkHolder.java   | 12 ++++
 .../security/authentication/Authentication.java    | 24 ++++---
 .../authentication/AuthenticationRequest.java      | 44 ++++++------
 .../AuthenticationRequestAbstract.java             | 23 +++++-
 .../{standard => }/Authenticator.java              | 32 +++++++--
 .../manager/AuthenticationManager.java             | 32 ++++-----
 .../standard/AuthenticatorAbstract.java            |  9 +--
 .../authentication/standard/Registrar.java         |  1 +
 .../authorization/{standard => }/Authorizor.java   | 25 ++++++-
 .../manager/AuthorizationManager.java              | 10 +--
 .../adoc/modules/command-log/pages/about.adoc      | 15 ++--
 .../secman/api/authorizor/AuthorizorSecman.java    | 16 ++---
 .../shiro/IsisModuleExtSecmanShiroRealm.java       |  2 +-
 security/adoc/modules/ROOT/pages/about.adoc        | 80 ++++++++++++++-------
 .../bypass/authorization/AuthorizorBypass.java     |  2 +-
 .../keycloak/IsisModuleSecurityKeycloak.java       |  2 -
 .../authentication/AuthenticatorKeycloak.java      |  2 +-
 .../keycloak/authorization/AuthorizorKeycloak.java | 57 ---------------
 .../shiro/authentication/AuthenticatorShiro.java   |  4 +-
 .../shiro/authorization/AuthorizorShiro.java       |  8 +--
 .../shiro/context/ShiroSecurityContext.java        |  4 +-
 .../spring/authentication/AuthenticatorSpring.java |  2 +-
 .../service/conneg/ContentNegotiationService.java  |  4 +-
 .../AuthenticatedWebSessionForIsis.java            | 32 ++++-----
 ...uthenticatedWebSessionForIsis_Authenticate.java | 14 ++--
 .../AuthenticatedWebSessionForIsis_SignIn.java     |  6 +-
 40 files changed, 537 insertions(+), 239 deletions(-)

diff --git a/antora/components/refguide-index/modules/_overview/pages/about.adoc b/antora/components/refguide-index/modules/_overview/pages/about.adoc
index d0fc381..2701bf5 100644
--- a/antora/components/refguide-index/modules/_overview/pages/about.adoc
+++ b/antora/components/refguide-index/modules/_overview/pages/about.adoc
@@ -1714,6 +1714,11 @@ org.junit.jupiter:junit-jupiter-engine:jar:<managed> +
 org.junit.vintage:junit-vintage-engine:jar:<managed> +
 ****
 
+.Document Index Entries
+****
+xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication], xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest], xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator], xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor]
+****
+
 |Apache Isis Core - Transaction
 [source,yaml]
 ----
@@ -2386,7 +2391,6 @@ Directory: /security/keycloak
 .Components
 ****
 o.a.i.security.keycloak.authentication.AuthenticatorKeycloak +
-o.a.i.security.keycloak.authorization.AuthorizorKeycloak +
 o.a.i.security.keycloak.webmodule.WebModuleKeycloak +
 ****
 
@@ -2400,7 +2404,7 @@ org.apache.isis.core:isis-core-webapp:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:security:index/keycloak/IsisModuleSecurityKeycloak.adoc[IsisModuleSecurityKeycloak], xref:refguide:security:index/keycloak/authentication/AuthenticatorKeycloak.adoc[AuthenticatorKeycloak], xref:refguide:security:index/keycloak/authorization/AuthorizorKeycloak.adoc[AuthorizorKeycloak], xref:refguide:security:index/keycloak/webmodule/KeycloakFilter.adoc[KeycloakFilter], xref:refguide:security:index/keycloak/webmodule/WebModuleKeycloak.adoc[WebModuleKeycloak]
+xref:refguide:security:index/keycloak/IsisModuleSecurityKeycloak.adoc[IsisModuleSecurityKeycloak], xref:refguide:security:index/keycloak/authentication/AuthenticatorKeycloak.adoc[AuthenticatorKeycloak], xref:refguide:security:index/keycloak/webmodule/KeycloakFilter.adoc[KeycloakFilter], xref:refguide:security:index/keycloak/webmodule/WebModuleKeycloak.adoc[WebModuleKeycloak]
 ****
 |===
 
@@ -3750,12 +3754,12 @@ skinparam {
 }
 hide stereotype
 left to right direction
-skinparam rectangle<<22>> {
+skinparam rectangle<<11>> {
   BackgroundColor #438dd5
   FontColor #fffffe
   BorderColor #2E6295
 }
-skinparam rectangle<<11>> {
+skinparam rectangle<<22>> {
   BackgroundColor #438dd5
   FontColor #fffffe
   BorderColor #2E6295
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/BookmarkHolder.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/BookmarkHolder.adoc
index b7552d1..5f7efb2 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/BookmarkHolder.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/BookmarkHolder.adoc
@@ -1,13 +1,29 @@
 = BookmarkHolder _(interface)_
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
+Can be optionally implemented by any object that is holds (either directly or implicitly) a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark] to a domain object.
+
+The framework provides mixins that surface the bookmarked domain object as either a property or an action of the holder.
+
 == API
 
 [source,java]
 .BookmarkHolder.java
 ----
 interface BookmarkHolder {
-  Bookmark bookmark()
+  Bookmark bookmark()     // <.>
 }
 ----
 
+<.> xref:#bookmark__[bookmark()]
++
+--
+A reference to an arbitrary domain object, as a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark] .
+--
+
+== Members
+
+[#bookmark__]
+=== bookmark()
+
+A reference to an arbitrary domain object, as a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark] .
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/hooks/BookmarkService_020-examples-and-usage.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/hooks/BookmarkService_020-examples-and-usage.adoc
index 027e0b9..f677e71 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/hooks/BookmarkService_020-examples-and-usage.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/bookmark/hooks/BookmarkService_020-examples-and-usage.adoc
@@ -1,4 +1,3 @@
-
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
 
@@ -16,23 +15,18 @@ which contributes a `lookup` action to return the referenced object
 +
 which contributes instead an `object` property, being the referenced object.
 
-Either of these can be suppressed, if required, using a vetoing subscriber that listens to the action or property domain event in order to hide the member.
+Either of these can be suppressed, if required, using a xref:userguide:btb:hints-and-tips.adoc#vetoing-visibility[vetoing subscriber] that listens to the action or property domain event in order to hide the member.
+
+== Examples
 
+For example, a `Customer` object with an xref:refguide:applib:index/annotation/DomainObject.adoc#objectType[object type] of "custmgmt.Customer" and an id of 123 would correspond to a xref:BookmarkService.adoc#bookmark[Bookmark] with a string representation of "custmgmt.Customer|123".
 
-// TODO: v2 - to fix up links.
+Bookmarks are useful to store a reference to an arbitrary object, although be aware that there is no referential integrity.
 
-//== Examples
-//
-//For example, a `Customer` object with an xref:refguide:applib:index/annotation/DomainObject.adoc#objectType[object type] of "custmgmt.Customer" and an id of 123
-//would correspond to a xref:BookmarkService.adoc#bookmark[Bookmark] with a string representation of "custmgmt.Customer|123".
-//
-//Bookmarks are useful to store a reference to an arbitrary object, although be aware that there is no referential integrity.
-//
-//Several of the extension libraries use bookmarks.
-//For example the xref:refguide:applib:index/services/publishing/spi/EntityPropertyChangeSubscriber.adoc[EntityPropertyChangeSubscriber] uses bookmarks to identify the object that is being modified.
-//
-//Serialized form of bookmarks also appear within  xref:refguide:schema:about.adoc[schema] instances, for example as used by xref:refguide:applib-svc:CommandServiceInternal.adoc[CommandService] and the xref:refguide:applib:index/services/publishing/spi/ExecutionSubscriber.adoc[ExecutionSubscriber].
+Several of the extension libraries use bookmarks.
+For example the xref:refguide:applib:index/services/publishing/spi/EntityPropertyChangeSubscriber.adoc[EntityPropertyChangeSubscriber] uses bookmarks to identify the object that is being modified.
 
+Serialized form of bookmarks also appear within  xref:refguide:schema:about.adoc[schema] instances, for example as used by xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] and the xref:refguide:applib:index/services/publishing/spi/ExecutionSubscriber.adoc[ExecutionSubscriber].
 
 == See Also
 
diff --git a/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc b/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc
index ad2fc47..1f7eb342 100644
--- a/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/interaction/session/InteractionFactory.adoc
@@ -30,7 +30,7 @@ If present, reuses the current top level _AuthenticationLayer_ , otherwise creat
 <.> xref:#openInteraction__Authentication[openInteraction(Authentication)]
 +
 --
-Returns a new or reused _AuthenticationLayer_ that is a holder of _Authentication_ on top of the current thread's authentication layer stack.
+Returns a new or reused _AuthenticationLayer_ that is a holder of xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] on top of the current thread's authentication layer stack.
 --
 <.> xref:#isInInteractionSession__[isInInteractionSession()]
 <.> xref:#callAuthenticated__Authentication_Callable[callAuthenticated(Authentication, Callable)]
@@ -69,7 +69,7 @@ If present, reuses the current top level _AuthenticationLayer_ , otherwise creat
 [#openInteraction__Authentication]
 === openInteraction(Authentication)
 
-Returns a new or reused _AuthenticationLayer_ that is a holder of _Authentication_ on top of the current thread's authentication layer stack.
+Returns a new or reused _AuthenticationLayer_ that is a holder of xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] on top of the current thread's authentication layer stack.
 
 If available reuses an existing _InteractionSession_ , otherwise creates a new one.
 
@@ -85,7 +85,7 @@ Executes a block of code with a new or reused _InteractionSession_ using a new o
 
 If there is currently no _InteractionSession_ a new one is created.
 
-If there is currently an _AuthenticationLayer_ that has an equal _Authentication_ to the given one, it is reused, otherwise a new one is created.
+If there is currently an _AuthenticationLayer_ that has an equal xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] to the given one, it is reused, otherwise a new one is created.
 
 [#runAuthenticated__Authentication_ThrowingRunnable]
 === runAuthenticated(Authentication, ThrowingRunnable)
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc
new file mode 100644
index 0000000..395288b
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authentication.adoc
@@ -0,0 +1,84 @@
+= Authentication _(interface)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+An immutable, serializable value type, that holds details about a user's authentication.
+
+== API
+
+[source,java]
+.Authentication.java
+----
+interface Authentication {
+  String getUserName()     // <.>
+  String getValidationCode()     // <.>
+  UserMemento getUser()     // <.>
+  ExecutionContext getExecutionContext()     // <.>
+  Type getType()     // <.>
+  Authentication withExecutionContext(ExecutionContext executionContext)     // <.>
+}
+----
+
+<.> xref:#getUserName__[getUserName()]
++
+--
+The name of the authenticated user; for display purposes only.
+--
+<.> xref:#getValidationCode__[getValidationCode()]
++
+--
+A unique code given to this session during authentication.
+--
+<.> xref:#getUser__[getUser()]
++
+--
+The (programmatically) simulated (or actual) user, belonging to this session.
+--
+<.> xref:#getExecutionContext__[getExecutionContext()]
++
+--
+The xref:refguide:applib:index/services/iactn/ExecutionContext.adoc[ExecutionContext] (programmatically) simulated (or actual), belonging to this session.
+--
+<.> xref:#getType__[getType()]
++
+--
+To support external security mechanisms such as keycloak, where the validity of the session is defined by headers in the request.
+--
+<.> xref:#withExecutionContext__ExecutionContext[withExecutionContext(ExecutionContext)]
++
+--
+Returns a copy with given _executionContext_ .
+--
+
+== Members
+
+[#getUserName__]
+=== getUserName()
+
+The name of the authenticated user; for display purposes only.
+
+[#getValidationCode__]
+=== getValidationCode()
+
+A unique code given to this session during authentication.
+
+This can be used to confirm that this session has been properly created and the user has been authenticated. It should return an empty string ( `""` ) if this is unauthenticated user
+
+[#getUser__]
+=== getUser()
+
+The (programmatically) simulated (or actual) user, belonging to this session.
+
+[#getExecutionContext__]
+=== getExecutionContext()
+
+The xref:refguide:applib:index/services/iactn/ExecutionContext.adoc[ExecutionContext] (programmatically) simulated (or actual), belonging to this session.
+
+[#getType__]
+=== getType()
+
+To support external security mechanisms such as keycloak, where the validity of the session is defined by headers in the request.
+
+[#withExecutionContext__ExecutionContext]
+=== withExecutionContext(ExecutionContext)
+
+Returns a copy with given _executionContext_ .
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc
new file mode 100644
index 0000000..4f6eefd
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authentication/AuthenticationRequest.adoc
@@ -0,0 +1,40 @@
+= AuthenticationRequest _(interface)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Represents a request to authenticate the user identified by _AuthenticationRequest#getName()_ .
+
+If successful, then the authentication mechanism is expected to add the _AuthenticationRequest#streamRoles() roles_ to the resultant xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] (obtained from the _org.apache.isis.applib.services.user.UserMemento_ returned by _Authentication#getUser()_ ).
+
+== API
+
+[source,java]
+.AuthenticationRequest.java
+----
+interface AuthenticationRequest {
+  String getName()     // <.>
+  Stream<String> streamRoles()     // <.>
+}
+----
+
+<.> xref:#getName__[getName()]
++
+--
+The name of the user to be authenticated by the configured xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] . Account's name.
+--
+<.> xref:#streamRoles__[streamRoles()]
++
+--
+The roles to be Account's roles as Stream.
+--
+
+== Members
+
+[#getName__]
+=== getName()
+
+The name of the user to be authenticated by the configured xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] . Account's name.
+
+[#streamRoles__]
+=== streamRoles()
+
+The roles to be Account's roles as Stream.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc
new file mode 100644
index 0000000..4c6f070
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authentication/Authenticator.adoc
@@ -0,0 +1,51 @@
+= Authenticator _(interface)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Represents an authentication mechanism capable of authenticating certain types of xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] and returning an xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if the credentials are valid.
+
+There can be multiple xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] s registered. If so, all Authenticators that can authenticate any given xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] must
+
+== API
+
+[source,java]
+.Authenticator.java
+----
+interface Authenticator {
+  boolean canAuthenticate(Class<? extends AuthenticationRequest> authenticationRequestClass)     // <.>
+  Authentication authenticate(AuthenticationRequest request, String code)     // <.>
+  void logout(Authentication authentication)     // <.>
+}
+----
+
+<.> xref:#canAuthenticate__Class[canAuthenticate(Class)]
++
+--
+Whether the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] is recognized by this xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] .
+--
+<.> xref:#authenticate__AuthenticationRequest_String[authenticate(AuthenticationRequest, String)]
++
+--
+Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if valid.
+--
+<.> xref:#logout__Authentication[logout(Authentication)]
++
+--
+Invalidates this xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] , meaning that the user will need to log in again to use the application.
+--
+
+== Members
+
+[#canAuthenticate__Class]
+=== canAuthenticate(Class)
+
+Whether the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] is recognized by this xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] .
+
+[#authenticate__AuthenticationRequest_String]
+=== authenticate(AuthenticationRequest, String)
+
+Authenticates the provided xref:refguide:core:index/security/authentication/AuthenticationRequest.adoc[AuthenticationRequest] , returning a non-null xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] if valid.
+
+[#logout__Authentication]
+=== logout(Authentication)
+
+Invalidates this xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] , meaning that the user will need to log in again to use the application.
diff --git a/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc b/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc
new file mode 100644
index 0000000..b2bf14d
--- /dev/null
+++ b/antora/components/refguide-index/modules/core/pages/index/security/authorization/Authorizor.adoc
@@ -0,0 +1,40 @@
+= Authorizor _(interface)_
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Represents a mechanism to evaluate whether the current user (as represented by xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can either view or invoke the domain object feature (as represented by xref:refguide:applib:index/Identifier.adoc[Identifier] .
+
+== API
+
+[source,java]
+.Authorizor.java
+----
+interface Authorizor {
+  boolean isVisible(Authentication authentication, Identifier identifier)     // <.>
+  boolean isUsable(Authentication authentication, Identifier identifier)     // <.>
+}
+----
+
+<.> xref:#isVisible__Authentication_Identifier[isVisible(Authentication, Identifier)]
++
+--
+Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+--
+<.> xref:#isUsable__Authentication_Identifier[isUsable(Authentication, Identifier)]
++
+--
+Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+--
+
+== Members
+
+[#isVisible__Authentication_Identifier]
+=== isVisible(Authentication, Identifier)
+
+Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can view the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+
+[#isUsable__Authentication_Identifier]
+=== isUsable(Authentication, Identifier)
+
+Whether the current xref:refguide:core:index/security/authentication/Authentication.adoc[Authentication] can invoke the domain object feature (represented by xref:refguide:applib:index/Identifier.adoc[Identifier] ).
+
+If this methods returns `false` then the feature will be greyed out/disabled.
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc b/antora/components/refguide-index/modules/extensions/pages/index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc
index 9ae67b0..a52b4ac 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/secman/shiro/IsisModuleExtSecmanShiroRealm.adoc
@@ -17,7 +17,7 @@ class IsisModuleExtSecmanShiroRealm {
 <.> xref:#IsisModuleExtSecmanShiroRealm__[IsisModuleExtSecmanShiroRealm()]
 +
 --
-Configures a _org.apache.shiro.authz.permission.PermissionResolver_ that knows how to process the permission strings that are provided by Isis' _Authorizor_ for Shiro.
+Configures a _org.apache.shiro.authz.permission.PermissionResolver_ that knows how to process the permission strings that are provided by Isis' xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] for Shiro.
 --
 
 == Members
@@ -25,4 +25,4 @@ Configures a _org.apache.shiro.authz.permission.PermissionResolver_ that knows h
 [#IsisModuleExtSecmanShiroRealm__]
 === IsisModuleExtSecmanShiroRealm()
 
-Configures a _org.apache.shiro.authz.permission.PermissionResolver_ that knows how to process the permission strings that are provided by Isis' _Authorizor_ for Shiro.
+Configures a _org.apache.shiro.authz.permission.PermissionResolver_ that knows how to process the permission strings that are provided by Isis' xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] for Shiro.
diff --git a/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc b/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
index 5ddf3c2..3292fc9 100644
--- a/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/shiro/authentication/AuthenticatorShiro.adoc
@@ -1,7 +1,7 @@
 = AuthenticatorShiro
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-If Shiro is configured for both authentication and authorization (as recommended), then this class is in the role of _Authenticator_ .
+If Shiro is configured for both authentication and authorization (as recommended), then this class is in the role of xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] .
 
 However, although there are two objects, they are set up to share the same _SecurityManager Shiro SecurityManager_ (bound to a thread-local).
 
diff --git a/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc b/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
index 2766594..f33bbde 100644
--- a/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
+++ b/antora/components/refguide-index/modules/security/pages/index/shiro/authorization/AuthorizorShiro.adoc
@@ -1,7 +1,7 @@
 = AuthorizorShiro
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-If Shiro is configured for both authentication and authorization (as recommended), then this class is in the role of _Authorizor_ .
+If Shiro is configured for both authentication and authorization (as recommended), then this class is in the role of xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] .
 
 However, although there are two objects, they are set up to share the same _SecurityManager Shiro SecurityManager_ (bound to a thread-local).
 
diff --git a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/service/conneg/ContentNegotiationService.adoc b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/service/conneg/ContentNegotiationService.adoc
index cd06d68..6299eeb 100644
--- a/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/service/conneg/ContentNegotiationService.adoc
+++ b/antora/components/refguide-index/modules/viewer/pages/index/restfulobjects/rendering/service/conneg/ContentNegotiationService.adoc
@@ -3,7 +3,9 @@
 
 Generates a representation according to HTTP `Accept` header of the request.
 
-This idea is discussed in section 34.1 of the
+This idea is discussed in section 34.1 of theRestful Objects specv1.0.
+
+The principal motivation is to allow more flexible representations to be generated for REST clients that (perhaps through their use of a certain JavaScript library, say) expect, or at least works best with, a certain style of representation.
 
 == API
 
diff --git a/antora/components/userguide/modules/btb/pages/hints-and-tips.adoc b/antora/components/userguide/modules/btb/pages/hints-and-tips.adoc
index f96ab45..d60da6c 100644
--- a/antora/components/userguide/modules/btb/pages/hints-and-tips.adoc
+++ b/antora/components/userguide/modules/btb/pages/hints-and-tips.adoc
@@ -14,8 +14,7 @@ include::hints-and-tips/are-you-sure.adoc[leveloffset=+1]
 include::hints-and-tips/custom-css.adoc[leveloffset=+1]
 include::hints-and-tips/replacing-default-service-implementations.adoc[leveloffset=+1]
 
-// incomplete, placeholder
-//include::hints-and-tips/vetoing-visibility.adoc[leveloffset=+1]
+include::hints-and-tips/vetoing-visibility.adoc[leveloffset=+1]
 
 include::hints-and-tips/transactions-and-errors.adoc[leveloffset=+1]
 include::hints-and-tips/persisted-title.adoc[leveloffset=+1]
diff --git a/antora/components/userguide/modules/btb/pages/hints-and-tips/vetoing-visibility.adoc b/antora/components/userguide/modules/btb/pages/hints-and-tips/vetoing-visibility.adoc
index 5cf02d2..50037e5 100644
--- a/antora/components/userguide/modules/btb/pages/hints-and-tips/vetoing-visibility.adoc
+++ b/antora/components/userguide/modules/btb/pages/hints-and-tips/vetoing-visibility.adoc
@@ -5,11 +5,29 @@
 :page-partial:
 
 
-NOTE: FIXME - a write-up of the "vetoing subscriber" design pattern, eg as described in the  xref:refguide:applib:index/services/bookmark/BookmarkService.adoc[BookmarkService]
+The framework provides a number of actions (domain service menu items or mixins) that you may wish to suppress from the user interface.
+This can be done by implementing a "vetoing subscriber" design pattern.
 
+For example, the xref:refguide:applib:index/services/bookmark/BookmarkService.adoc[BookmarkService] has a related interface, xref:refguide:applib:index/services/bookmark/BookmarkHolder.adoc[BookmarkHolder], for objects that holds a reference to another domain object implicitly as a xref:refguide:applib:index/services/bookmark/Bookmark.adoc[Bookmark].
 
-eg if included an addon such as auditing or security.
+The xref:refguide:applib:index/services/bookmark/BookmarkHolder_object.adoc[BookmarkHolder_object] mixin surfaces the related domain object as an "object" property of the `BookmarkHolder`.
 
-solution is to write a domain event subscriber that vetoes the visibility
+If you want to suppress this property, a vetoing subscriber can listen to the associated domain event of the mixin:
 
-All the addons actions inherit from common base classes so this can be as broad-brush or fine-grained as required
+[source, java]
+.HideBookmarkHolderObjectProperty.java
+----
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Service;
+
+@Service
+public class HideBookmarkHolderObjectProperty {
+
+    @EventListener(BookmarkHolder_object.PropertyDomainEvent.class)
+    public void on(BookmarkHolder_object.PropertyDomainEvent ev) {
+        ev.hide();
+    }
+}
+----
+
+These domain events will often have a superclass, in which case the vetoing subscriber can be as broad-brush or fine-grained as required.
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolder.java b/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolder.java
index 0a81f1c..73b2293 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolder.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/BookmarkHolder.java
@@ -19,8 +19,20 @@
 package org.apache.isis.applib.services.bookmark;
 
 /**
+ * Can be optionally implemented by any object that is holds (either directly
+ * or implicitly) a {@link Bookmark} to a domain object.
+ *
+ * <p>
+ *     The framework provides mixins that surface the bookmarked domain
+ *     object as either a property or an action of the holder.
+ * </p>
+ *
  * @since 1.x {@index}
  */
 public interface BookmarkHolder {
+
+    /**
+     * A reference to an arbitrary domain object, as a {@link Bookmark}.
+     */
     Bookmark bookmark();
 }
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/Authentication.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/Authentication.java
index 2a06aed..134a575 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/Authentication.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/Authentication.java
@@ -26,9 +26,11 @@ import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.user.UserMemento;
 
 /**
- * An immutable, serializable value type, that holds details about a user's authentication. 
- * 
- * @since 2.0
+ * An immutable, serializable value type, that holds details about a user's authentication.
+ *
+ * @apiNote This is a framework internal class and so does not constitute a formal API.
+ *
+ * @since 2.0 {@index}
  */
 public interface Authentication extends Serializable {
 
@@ -51,19 +53,19 @@ public interface Authentication extends Serializable {
 
     /**
      * The (programmatically) simulated (or actual) user, belonging to this session.
-     * 
-     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its 
-     * own simulated (or actual) user 
+     *
+     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its
+     * own simulated (or actual) user
      */
     default UserMemento getUser() {
         return getExecutionContext().getUser();
     }
-    
+
     /**
      * The {@link ExecutionContext} (programmatically) simulated (or actual), belonging to this session.
-     * 
-     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its 
-     * own simulated (or actual) clock 
+     *
+     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its
+     * own simulated (or actual) clock
      */
     ExecutionContext getExecutionContext();
 
@@ -87,7 +89,7 @@ public interface Authentication extends Serializable {
     }
 
     // -- WITHERS
-    
+
     /**
      * Returns a copy with given {@code executionContext}.
      * @param executionContext
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequest.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequest.java
index d2f0acb..5057992 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequest.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequest.java
@@ -19,43 +19,43 @@
 
 package org.apache.isis.core.security.authentication;
 
-import java.util.Collection;
 import java.util.stream.Stream;
 
 import javax.annotation.Nullable;
 
 import static org.apache.isis.commons.internal.base._NullSafe.stream;
 
+/**
+ * Represents a request to authenticate the user identified by
+ * {@link AuthenticationRequest#getName()}.
+ *
+ * <p>
+ *     If successful, then the authentication mechanism is expected to add the
+ *     {@link AuthenticationRequest#streamRoles() roles} to the resultant
+ *     {@link Authentication} (obtained from the
+ *     {@link org.apache.isis.applib.services.user.UserMemento} returned by
+ *     {@link Authentication#getUser()}).
+ * </p>
+ *
+ * @apiNote This is a framework internal class and so does not constitute a formal API.
+ *
+ * @since 1.x - refactored/renamed for v2 {@index}
+ */
 public interface AuthenticationRequest {
 
     /**
-     * Account's name. 
+     * The name of the user to be authenticated by the configured
+     * {@link Authenticator}.
+     * Account's name.
      * @return nullable
      */
-    public @Nullable String getName();
+    @Nullable String getName();
 
     /**
-     * Account's roles as Stream.
+     * The roles to be  Account's roles as Stream.
      * @return non-null
      * @since 2.0
      */
-    public Stream<String> streamRoles();
-
-    /**
-     * Add a role to associate with the account. Null or empty roles are ignored.
-     * @param role
-     * @since 2.0
-     */
-    public void addRole(@Nullable String role);
-
-    /**
-     * Add a roles to associate with the account. Null or empty roles are ignored.
-     * @param roles
-     * @since 2.0
-     */
-    public default void addRoles(@Nullable Collection<String> roles) {
-        stream(roles)
-        .forEach(this::addRole);
-    }
+    Stream<String> streamRoles();
 
 }
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
index 2c639b9..b379fe6 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/AuthenticationRequestAbstract.java
@@ -19,12 +19,17 @@
 
 package org.apache.isis.core.security.authentication;
 
+import java.util.Collection;
 import java.util.Set;
 import java.util.stream.Stream;
 
+import javax.annotation.Nullable;
+
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Sets;
 
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+
 public abstract class AuthenticationRequestAbstract implements AuthenticationRequest {
 
     private final String name;
@@ -44,7 +49,18 @@ public abstract class AuthenticationRequestAbstract implements AuthenticationReq
         return roles.stream();
     }
 
-    @Override
+    /**
+     * Add a role to associate with the account.
+     *
+     * <p>
+     * Null or empty roles are ignored.
+     * </p>
+     *
+     * @apiNote this is not part of the {@link AuthenticationRequest} API.
+     *
+     * @param role
+     * @since 2.0
+     */
     public void addRole(String role) {
         if(_Strings.isNullOrEmpty(role)) {
             return; // ignore
@@ -52,4 +68,9 @@ public abstract class AuthenticationRequestAbstract implements AuthenticationReq
         this.roles.add(role);
     }
 
+    public void addRoles(@Nullable Collection<String> roles) {
+        stream(roles)
+                .forEach(this::addRole);
+    }
+
 }
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Authenticator.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/Authenticator.java
similarity index 53%
rename from core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Authenticator.java
rename to core/security/src/main/java/org/apache/isis/core/security/authentication/Authenticator.java
index 7c3fb17..34728d5 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Authenticator.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/Authenticator.java
@@ -17,11 +17,23 @@
  *  under the License.
  */
 
-package org.apache.isis.core.security.authentication.standard;
-
-import org.apache.isis.core.security.authentication.AuthenticationRequest;
-import org.apache.isis.core.security.authentication.Authentication;
+package org.apache.isis.core.security.authentication;
 
+/**
+ * Represents an authentication mechanism capable of authenticating certain
+ * types of {@link AuthenticationRequest} and returning an {@link Authentication}
+ * if the credentials are valid.
+ *
+ * <p>
+ *     There can be multiple {@link Authenticator}s registered.  If so, all
+ *     Authenticators that can authenticate any given {@link AuthenticationRequest}
+ *     must
+ * </p>
+ *
+ * @apiNote This is a framework internal class and so does not constitute a formal API.
+ *
+ * @since 1.x but refactored in v2 {@index}
+ */
 public interface Authenticator {
 
     /**
@@ -31,11 +43,17 @@ public interface Authenticator {
     boolean canAuthenticate(Class<? extends AuthenticationRequest> authenticationRequestClass);
 
     /**
+     * Authenticates the provided {@link AuthenticationRequest request},
+     * returning a non-null {@link Authentication} if valid.
+     *
      * @param code
-     *            - a hint; is guaranteed to be unique, but the authenticator
-     *            decides whether to use it or not.
+     *            - a hint; is guaranteed by the framework to be unique, but the authenticator decides whether to use it or not.
      */
     Authentication authenticate(AuthenticationRequest request, String code);
 
-    void logout(Authentication session);
+    /**
+     * Invalidates this {@link Authentication}, meaning that the user will need
+     * to log in again to use the application.
+     */
+    void logout(Authentication authentication);
 }
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
index 12d7897..779da22 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/manager/AuthenticationManager.java
@@ -39,7 +39,7 @@ import org.apache.isis.commons.internal.base._Timing;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.core.security.authentication.Authentication;
 import org.apache.isis.core.security.authentication.AuthenticationRequest;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 import org.apache.isis.core.security.authentication.standard.RandomCodeGenerator;
 import org.apache.isis.core.security.authentication.standard.Registrar;
 
@@ -54,21 +54,21 @@ import lombok.val;
 public class AuthenticationManager {
 
     @Getter private final Can<Authenticator> authenticators;
-    
+
     private final Map<String, String> userByValidationCode = _Maps.newConcurrentHashMap();
     private final RandomCodeGenerator randomCodeGenerator;
     private final Can<Registrar> registrars;
 
     @Inject
     public AuthenticationManager(
-            final List<Authenticator> injectedAuthenticators,
+            final List<Authenticator> authenticators,
             final RandomCodeGenerator randomCodeGenerator) {
         this.randomCodeGenerator = randomCodeGenerator;
-        this.authenticators = Can.ofCollection(injectedAuthenticators);
-        if (authenticators.isEmpty()) {
+        this.authenticators = Can.ofCollection(authenticators);
+        if (this.authenticators.isEmpty()) {
             throw new NoAuthenticatorException("No authenticators specified");
         }
-        this.registrars = authenticators
+        this.registrars = this.authenticators
                 .filter(Registrar.class::isInstance)
                 .map(Registrar.class::cast);
     }
@@ -76,19 +76,19 @@ public class AuthenticationManager {
     // -- SESSION MANAGEMENT (including authenticate)
 
     public final Authentication authenticate(AuthenticationRequest request) {
-        
+
         if (request == null) {
             return null;
         }
 
         val compatibleAuthenticators = authenticators
                 .filter(authenticator->authenticator.canAuthenticate(request.getClass()));
-                
+
         if (compatibleAuthenticators.isEmpty()) {
             throw new NoAuthenticatorException(
                     "No authenticator available for processing " + request.getClass().getName());
         }
-        
+
         for (val authenticator : compatibleAuthenticators) {
             val authentication = authenticator.authenticate(request, getUnusedRandomCode());
             if (authentication != null) {
@@ -96,23 +96,23 @@ public class AuthenticationManager {
                 return authentication;
             }
         }
-        
+
         return null;
     }
-    
+
     private String getUnusedRandomCode() {
-        
+
         val stopWatch = _Timing.now();
-        
+
         String code;
         do {
-            
+
             // guard against infinite loop when unique code generation for some reason fails
             if(stopWatch.getMillis()>3000L) {
                 throw new NoAuthenticatorException(
                         "RandomCodeGenerator failed to produce a unique code within 3s.");
             }
-            
+
             code = randomCodeGenerator.generateRandomCode();
         } while (userByValidationCode.containsKey(code));
 
@@ -163,7 +163,7 @@ public class AuthenticationManager {
 
 
     // -- DEBUGGING
- 
+
     private static final ToString<AuthenticationManager> toString =
             ToString.<AuthenticationManager>toString("class", obj->obj.getClass().getSimpleName())
             .thenToString("authenticators", obj->""+obj.authenticators.size())
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/AuthenticatorAbstract.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/AuthenticatorAbstract.java
index 10c3040..8f44235 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/AuthenticatorAbstract.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/AuthenticatorAbstract.java
@@ -22,6 +22,7 @@ package org.apache.isis.core.security.authentication.standard;
 import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.core.security.authentication.AuthenticationRequest;
 import org.apache.isis.core.security.authentication.Authentication;
+import org.apache.isis.core.security.authentication.Authenticator;
 
 import lombok.val;
 
@@ -33,14 +34,14 @@ public abstract class AuthenticatorAbstract implements Authenticator {
      */
     @Override
     public final Authentication authenticate(
-            final AuthenticationRequest request, 
+            final AuthenticationRequest request,
             final String validationCode) {
-        
+
         if (!isValid(request)) {
             return null;
         }
-        
-        val user = UserMemento.ofNameAndRoleNames(request.getName(), request.streamRoles()); 
+
+        val user = UserMemento.ofNameAndRoleNames(request.getName(), request.streamRoles());
         return SimpleAuthentication.of(user, validationCode);
     }
 
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Registrar.java b/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Registrar.java
index 0435479..ca2becb 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Registrar.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authentication/standard/Registrar.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.core.security.authentication.standard;
 
+import org.apache.isis.core.security.authentication.Authenticator;
 import org.apache.isis.core.security.authentication.manager.RegistrationDetails;
 
 public interface Registrar extends Authenticator {
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authorization/standard/Authorizor.java b/core/security/src/main/java/org/apache/isis/core/security/authorization/Authorizor.java
similarity index 57%
rename from core/security/src/main/java/org/apache/isis/core/security/authorization/standard/Authorizor.java
rename to core/security/src/main/java/org/apache/isis/core/security/authorization/Authorizor.java
index 9ce5c88..37a7711 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authorization/standard/Authorizor.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authorization/Authorizor.java
@@ -17,14 +17,37 @@
  *  under the License.
  */
 
-package org.apache.isis.core.security.authorization.standard;
+package org.apache.isis.core.security.authorization;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.core.security.authentication.Authentication;
 
+/**
+ * Represents a mechanism to evaluate whether the current user (as represented
+ * by {@link Authentication} can either view or invoke the domain object
+ * feature (as represented by {@link Identifier}.
+ *
+ * @apiNote This is a framework internal class and so does not constitute a formal API.
+ *
+ * @since 1.x but refactored in v2 {@index}
+ */
 public interface Authorizor {
 
+    /**
+     * Whether the current {@link Authentication user} can view the
+     * domain object feature (represented by {@link Identifier}).
+     */
     boolean isVisible(Authentication authentication, Identifier identifier);
+
+    /**
+     * Whether the current {@link Authentication user} can invoke the
+     * domain object feature (represented by {@link Identifier}).
+     *
+     * <p>
+     *     If this methods returns <code>false</code> then the feature will be
+     *     greyed out/disabled.
+     * </p>
+     */
     boolean isUsable(Authentication authentication, Identifier identifier);
 
 }
diff --git a/core/security/src/main/java/org/apache/isis/core/security/authorization/manager/AuthorizationManager.java b/core/security/src/main/java/org/apache/isis/core/security/authorization/manager/AuthorizationManager.java
index 60c7588..8fdbecf 100644
--- a/core/security/src/main/java/org/apache/isis/core/security/authorization/manager/AuthorizationManager.java
+++ b/core/security/src/main/java/org/apache/isis/core/security/authorization/manager/AuthorizationManager.java
@@ -32,7 +32,7 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.sudo.SudoService;
 import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authorization.Authorizor;
 
 /**
  * Authorizes the user in the current session view and use members of an object.
@@ -60,7 +60,7 @@ public class AuthorizationManager {
      * </p>
      */
     public boolean isUsable(
-            final Authentication authentication, 
+            final Authentication authentication,
             final Identifier identifier) {
         if (isPerspectiveMember(identifier)) {
             return true;
@@ -83,7 +83,7 @@ public class AuthorizationManager {
      * </p>
      */
     public boolean isVisible(
-            final Authentication authentication, 
+            final Authentication authentication,
             final Identifier identifier) {
         if (isPerspectiveMember(identifier)) {
             return true;
@@ -102,7 +102,7 @@ public class AuthorizationManager {
     }
 
     // -- HELPER
-    
+
     private static boolean containsSudoSuperuserRole(
             final @Nullable Authentication session) {
         if(session==null || session.getUser()==null) {
@@ -110,7 +110,7 @@ public class AuthorizationManager {
         }
         return session.getUser().hasRoleName(SudoService.ACCESS_ALL_ROLE.getName());
     }
-    
+
     private boolean isPerspectiveMember(final Identifier identifier) {
         return (identifier.getClassName().equals(""));
     }
diff --git a/extensions/core/command-log/adoc/modules/command-log/pages/about.adoc b/extensions/core/command-log/adoc/modules/command-log/pages/about.adoc
index 72cbd9e..58a4652 100644
--- a/extensions/core/command-log/adoc/modules/command-log/pages/about.adoc
+++ b/extensions/core/command-log/adoc/modules/command-log/pages/about.adoc
@@ -7,15 +7,14 @@
 WARNING: TODO: v2 - this code has not yet been brought into the framework.
 
 The _command-log_ module provides an implementation that persists ``Command``s using the xref:pjdo:ROOT:about.adoc[JDO/DataNucleus] object store.
-It further provides a number of supporting services:
 
-* `org.isisaddons.module.command.dom.CommandServiceJdoRepository` is a repository to search for persisted ``Command``s
-
-* `org.isisaddons.module.command.dom.CommandServiceJdoContributions` contributes actions for searching for persisted child and sibling ``Command``s.
-
-All of these can be activated by updating the `pom.xml` and updating the `AppManifest#getModules()` method.
-
-If contributions are not required in the UI, these can be suppressed either using security or by implementing a xref:userguide:btb:about.adoc#vetoing-visibility[vetoing subscriber].
+//It further provides a number of supporting services:
+//
+//* `org.isisaddons.module.command.dom.CommandServiceJdoRepository` is a repository to search for persisted ``Command``s
+//
+//* `org.isisaddons.module.command.dom.CommandServiceJdoContributions` contributes actions for searching for persisted child and sibling ``Command``s.
+//
+//If contributions are not required in the UI, these can be suppressed either using security or by implementing a xref:userguide:btb:hints-and-tips.adoc#vetoing-visibility[vetoing subscriber].
 
 
 
diff --git a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
index 74ee407..dc3188a 100644
--- a/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
+++ b/extensions/security/secman/api/src/main/java/org/apache/isis/extensions/secman/api/authorizor/AuthorizorSecman.java
@@ -29,7 +29,7 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.core.metamodel.services.appfeat.ApplicationFeatureId;
 import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authorization.Authorizor;
 import org.apache.isis.extensions.secman.api.permission.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.user.ApplicationUser;
 import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
@@ -44,7 +44,7 @@ import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
 public class AuthorizorSecman implements Authorizor {
 
     @Inject ApplicationUserRepository<? extends ApplicationUser> applicationUserRepository;
-    
+
     @Override
     public boolean isVisible(final Authentication authentication, final Identifier identifier) {
         return grants(authentication, identifier, ApplicationPermissionMode.VIEWING);
@@ -54,19 +54,19 @@ public class AuthorizorSecman implements Authorizor {
     public boolean isUsable(final Authentication authentication, final Identifier identifier) {
         return grants(authentication, identifier, ApplicationPermissionMode.CHANGING);
     }
-    
+
     // -- HELPER
-    
+
     private boolean grants(
-            final Authentication authentication, 
-            final Identifier identifier, 
+            final Authentication authentication,
+            final Identifier identifier,
             final ApplicationPermissionMode permissionMode) {
-        
+
         return applicationUserRepository
         .findByUsername(authentication.getUserName())
         .map(ApplicationUser::getPermissionSet)
         .map(permissionSet->permissionSet.grants(
-                ApplicationFeatureId.fromIdentifier(identifier), 
+                ApplicationFeatureId.fromIdentifier(identifier),
                 permissionMode))
         .orElse(false);
     }
diff --git a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
index b023bfd..1c739a4 100644
--- a/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
+++ b/extensions/security/secman/shiro-realm/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleExtSecmanShiroRealm.java
@@ -44,7 +44,7 @@ import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.core.interaction.session.InteractionFactory;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authorization.Authorizor;
 import org.apache.isis.extensions.secman.api.SecmanConfiguration;
 import org.apache.isis.extensions.secman.api.SecurityRealm;
 import org.apache.isis.extensions.secman.api.SecurityRealmCharacteristic;
diff --git a/security/adoc/modules/ROOT/pages/about.adoc b/security/adoc/modules/ROOT/pages/about.adoc
index 9709087..0905a6b 100644
--- a/security/adoc/modules/ROOT/pages/about.adoc
+++ b/security/adoc/modules/ROOT/pages/about.adoc
@@ -9,42 +9,31 @@ This guide describes the authentication and authorization features available to
 
 
 
-
-
-
 == Terminology
 
-// TODO:v2: these words could perhaps move into the "security API" module, currently empty.
-
 Apache Isis has built-in support for authentication and authorization:
 
 * By "authentication" we mean logging into the application using some credentials, typically a username and password.
 Authentication also means looking up the set of roles to which a user belongs.
++
+The framework allows for different authentication mechanisms through the xref:refguide:core:index/security/authentication/Authenticator.adoc[Authenticator] SPI.
+.
 
-* By "authorization" we mean permissions: granting roles to have access to features (object member) of the app.
+* By "authorization" we mean permissions: granting roles to have access to features (domain object members) of the app.
++
+The framework allows for different authorization mechanisms through the xref:refguide:core:index/security/authorization/Authorizor.adoc[Authorizor] SPI.
 
-Apache Isis has two levels of permissions.
-_Read_ permission means that the user can view the object member; it will be rendered in the UI.  An action with only read permission will be shown disabled ("greyed out".
-_Write_ permission means that the object member can be changed.  For actions this means that they can be invoked.
+There are two levels of permissions:
 
-//WARNING: TODO: v2: this is out of date, because there is also a keycloak integration and a Spring implementatoin.
+* _Read_ permission means that the user can view the object member; it will be rendered in the UI.
++
+An action with only read permission will be shown disabled ("greyed out"); a property with read-only permission cannot be edited.
 
-The framework provides an API for both authentication and authorization, and provides an implementation that integrates with link:http://shiro.apache.org[Apache Shiro].
-Shiro in turn uses the concept of a _realm_ as a source for both authentication and optionally authorization.
-
-//WARNING: TODO: v2: Spring Boot requires that shiro.ini is on classpath, not in WEB-INF.
+* _Write_ permission means that the object member can be changed.
++
+For actions this means that they can be invoked.
 
-Shiro ships with a simple text-based realm -- the `IniRealm` -- which reads users (and password), user roles and role permissions from the `WEB-INF/shiro.ini` file.
-The xref:docs:starters:helloworld.adoc[HelloWorld] and xref:docs:starters:simpleapp.adoc[SimpleApp] starter apps are both configured to use this realm.
-
-Shiro also ships with an implementation of an LDAP-based realm; LDAP is often used to manage user/passwords and corresponding user groups.
-Apache Isis in turn extends this with its `IsisLdapRealm`, which provides more flexibility for both group/role and role/permissions management.
-
-In addition, the xref:security:ROOT:about.adoc[SecMan extension] provides an implementation of the Shiro `Realm` API.
-This extension also represents users, roles and permissions as domain objects, allowing them to be administered through Apache Isis itself.
-Moreover, it can also optionally delegate password management to a subsidiary (delegate) realm (usually LDAP as discussed above).
-
-In addition to Apache Isis' Shiro-based implementation of its authentication and authorization APIs, Isis also provides a "bypass" implementation, useful for quick-n-dirty prototyping when you want to in effect disable (bypass) security completely.
+If there is neither _read_ nor _write_ permissions then the feature will be invisible to the user.
 
 [NOTE]
 .What about auditing?
@@ -59,3 +48,44 @@ For xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[Co
 The xref:extensions:command-log:about.adoc[Command Log] extension provides a simple implementation of this SPI.
 ====
 
+
+== Implementations
+
+[#shiro]
+=== Shiro
+
+The framework provides an API for both authentication and authorization, and provides an implementation that integrates with link:http://shiro.apache.org[Apache Shiro].
+Shiro in turn uses the concept of a _realm_ as a source for both authentication and optionally authorization.
+
+Shiro ships with a simple text-based realm -- the `IniRealm` -- which reads users (and password), user roles and role permissions from the `WEB-INF/shiro.ini` file.
+The xref:docs:starters:helloworld.adoc[HelloWorld] and xref:docs:starters:simpleapp.adoc[SimpleApp] starter apps are both configured to use this realm.
+
+The Shiro framework ships with an implementation of an LDAP-based realm; LDAP is often used to manage user/passwords and corresponding user groups.
+Apache Isis extends Shiro's implementation this  `IsisLdapRealm`, which provides more flexibility for both group/role and role/permissions management.
+
+
+=== Bypass
+
+The framework provides a "bypass" implementation, useful for quick-n-dirty prototyping when you want to in effect disable (bypass) security completely.
+
+=== KeyCloak
+
+WARNING: TODO: v2 - not yet documented.
+
+=== Spring
+
+WARNING: TODO: v2 - WIP, not yet documented.
+
+== SecMan
+
+The xref:security:ROOT:about.adoc[SecMan extension]'s primary purpose is for authorisation, defining a database of roles and permissions associated with
+those roles.
+It also maps users to roles.
+
+As these users, roles and permissions are domain objects, they can be administered through Apache Isis itself.
+
+Because each user to be authorised must exist in the SecMan database, this means that it can also act as a secondary authenticator.
+It does this by providing an implementation of the Shiro `Realm` API.
+Using this design the password management can be handled to a subsidiary (delegate) Shiro realm (for example, LDAP, as discussed <<shiro, above>>).
+
+
diff --git a/security/bypass/src/main/java/org/apache/isis/security/bypass/authorization/AuthorizorBypass.java b/security/bypass/src/main/java/org/apache/isis/security/bypass/authorization/AuthorizorBypass.java
index b2a9aee..728edf1 100644
--- a/security/bypass/src/main/java/org/apache/isis/security/bypass/authorization/AuthorizorBypass.java
+++ b/security/bypass/src/main/java/org/apache/isis/security/bypass/authorization/AuthorizorBypass.java
@@ -28,7 +28,7 @@ import org.springframework.stereotype.Service;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authorization.Authorizor;
 
 /**
  * @since 1.x {@index}
diff --git a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/IsisModuleSecurityKeycloak.java b/security/keycloak/src/main/java/org/apache/isis/security/keycloak/IsisModuleSecurityKeycloak.java
index 9bb35c9..213a0c7 100644
--- a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/IsisModuleSecurityKeycloak.java
+++ b/security/keycloak/src/main/java/org/apache/isis/security/keycloak/IsisModuleSecurityKeycloak.java
@@ -23,7 +23,6 @@ import org.springframework.context.annotation.Import;
 
 import org.apache.isis.core.runtimeservices.IsisModuleCoreRuntimeServices;
 import org.apache.isis.security.keycloak.authentication.AuthenticatorKeycloak;
-import org.apache.isis.security.keycloak.authorization.AuthorizorKeycloak;
 import org.apache.isis.security.keycloak.webmodule.WebModuleKeycloak;
 import org.apache.isis.core.webapp.IsisModuleCoreWebapp;
 
@@ -40,7 +39,6 @@ import org.apache.isis.core.webapp.IsisModuleCoreWebapp;
 
         // @Service's
         AuthenticatorKeycloak.class,
-        AuthorizorKeycloak.class,
         WebModuleKeycloak.class,
 
 })
diff --git a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authentication/AuthenticatorKeycloak.java b/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authentication/AuthenticatorKeycloak.java
index f9d72f5..260a6c7 100644
--- a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authentication/AuthenticatorKeycloak.java
+++ b/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authentication/AuthenticatorKeycloak.java
@@ -30,7 +30,7 @@ import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.core.security.authentication.AuthenticationRequest;
 import org.apache.isis.core.security.authentication.Authentication;
 import org.apache.isis.core.security.authentication.AuthenticationContext;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 
 /**
  * @since 2.0 {@index}
diff --git a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authorization/AuthorizorKeycloak.java b/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authorization/AuthorizorKeycloak.java
deleted file mode 100644
index 3246a7e..0000000
--- a/security/keycloak/src/main/java/org/apache/isis/security/keycloak/authorization/AuthorizorKeycloak.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.security.keycloak.authorization;
-
-
-import javax.inject.Named;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
-
-/**
- * @since 2.0 {@index}
- */
-@Service
-@Named("isis.security.AuthorizorKeycloak")
-@Order(OrderPrecedence.EARLY)
-@Qualifier("Keycloak")
-public class AuthorizorKeycloak implements Authorizor {
-
-    @Override
-    public boolean isVisible(final Authentication authentication, Identifier identifier) {
-        return isPermitted(identifier, "r");
-    }
-
-    @Override
-    public boolean isUsable(final Authentication authentication, Identifier identifier) {
-        return isPermitted(identifier, "w");
-    }
-
-    private boolean isPermitted(Identifier identifier, String qualifier) {
-        return true;
-    }
-
-
-}
diff --git a/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java b/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
index 8439a9c..8e1f471 100644
--- a/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
+++ b/security/shiro/src/main/java/org/apache/isis/security/shiro/authentication/AuthenticatorShiro.java
@@ -53,9 +53,9 @@ import org.apache.isis.core.config.IsisConfiguration;
 import org.apache.isis.core.security.authentication.AuthenticationRequest;
 import org.apache.isis.core.security.authentication.AuthenticationRequestPassword;
 import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 import org.apache.isis.core.security.authentication.standard.SimpleAuthentication;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authorization.Authorizor;
 import org.apache.isis.security.shiro.context.ShiroSecurityContext;
 
 import lombok.val;
diff --git a/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/AuthorizorShiro.java b/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/AuthorizorShiro.java
index 9dc9214..6017894 100644
--- a/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/AuthorizorShiro.java
+++ b/security/shiro/src/main/java/org/apache/isis/security/shiro/authorization/AuthorizorShiro.java
@@ -32,8 +32,8 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.core.security.authentication.Authentication;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authentication.Authenticator;
+import org.apache.isis.core.security.authorization.Authorizor;
 import org.apache.isis.security.shiro.context.ShiroSecurityContext;
 
 import lombok.val;
@@ -43,7 +43,7 @@ import lombok.val;
  * in the role of {@link Authorizor}.
  *
  * <p>
- * However, although there are two objects, they are set up to share the same 
+ * However, although there are two objects, they are set up to share the same
  * {@link SecurityManager Shiro SecurityManager}
  * (bound to a thread-local).
  * </p>
@@ -77,7 +77,7 @@ public class AuthorizorShiro implements Authorizor {
 
         final Subject subject = SecurityUtils.getSubject();
         final String permission = asPermissionsString(identifier) + ":" + qualifier;
-        
+
         try {
             _Assert.assertEquals(userName, subject.getPrincipal().toString());
             return subject.isPermitted(permission);
diff --git a/security/shiro/src/main/java/org/apache/isis/security/shiro/context/ShiroSecurityContext.java b/security/shiro/src/main/java/org/apache/isis/security/shiro/context/ShiroSecurityContext.java
index de9e6df..95f25db 100644
--- a/security/shiro/src/main/java/org/apache/isis/security/shiro/context/ShiroSecurityContext.java
+++ b/security/shiro/src/main/java/org/apache/isis/security/shiro/context/ShiroSecurityContext.java
@@ -23,8 +23,8 @@ import org.apache.shiro.UnavailableSecurityManagerException;
 import org.apache.shiro.mgt.RealmSecurityManager;
 import org.apache.shiro.mgt.SecurityManager;
 
-import org.apache.isis.core.security.authentication.standard.Authenticator;
-import org.apache.isis.core.security.authorization.standard.Authorizor;
+import org.apache.isis.core.security.authentication.Authenticator;
+import org.apache.isis.core.security.authorization.Authorizor;
 
 /**
  * @since 2.0
diff --git a/security/spring/src/main/java/org/apache/isis/security/spring/authentication/AuthenticatorSpring.java b/security/spring/src/main/java/org/apache/isis/security/spring/authentication/AuthenticatorSpring.java
index b8866a7..8ef8490 100644
--- a/security/spring/src/main/java/org/apache/isis/security/spring/authentication/AuthenticatorSpring.java
+++ b/security/spring/src/main/java/org/apache/isis/security/spring/authentication/AuthenticatorSpring.java
@@ -30,7 +30,7 @@ import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.core.security.authentication.Authentication;
 import org.apache.isis.core.security.authentication.AuthenticationContext;
 import org.apache.isis.core.security.authentication.AuthenticationRequest;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 
 /**
  * @since 2.0 {@index}
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationService.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationService.java
index 580dcb2..93d7353 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationService.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationService.java
@@ -32,7 +32,7 @@ import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndAc
  *
  * <p>
  *  This idea is discussed in section 34.1 of the
- *  <a href="http://restfulobjects.org>Restful Objects spec</a> v1.0.
+ *  <a href="http://restfulobjects.org">Restful Objects spec</a> v1.0.
  * </p>
  *
  * <p>
@@ -42,6 +42,8 @@ import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndAc
  * style of representation.
  * </p>
  *
+ * @apiNote This domain service uses internal framework classes and so does not constitute a formal API/SPI for the framework
+ *
  * @since 1.x {@index}
  */
 public interface ContentNegotiationService {
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
index 85bbf59..2a350f5 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis.java
@@ -53,8 +53,8 @@ import lombok.val;
  * also tracks thread usage (so that multiple concurrent requests are all
  * associated with the same session).
  */
-public class AuthenticatedWebSessionForIsis 
-extends AuthenticatedWebSession 
+public class AuthenticatedWebSessionForIsis
+extends AuthenticatedWebSession
 implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonContext {
 
     private static final long serialVersionUID = 1L;
@@ -65,8 +65,8 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
         return (AuthenticatedWebSessionForIsis) Session.get();
     }
 
-    @Getter protected transient IsisAppCommonContext commonContext; 
-    
+    @Getter protected transient IsisAppCommonContext commonContext;
+
     private BreadcrumbModel breadcrumbModel;
     private BookmarkedPagesModel bookmarkedPagesModel;
 
@@ -88,7 +88,7 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
 
     @Override
     public synchronized boolean authenticate(final String username, final String password) {
-        AuthenticationRequest authenticationRequest = new AuthenticationRequestPassword(username, password);
+        val authenticationRequest = new AuthenticationRequestPassword(username, password);
         authenticationRequest.addRole(USER_ROLE);
         this.authentication = getAuthenticationManager().authenticate(authenticationRequest);
         if (this.authentication != null) {
@@ -119,9 +119,9 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
 
         getAuthenticationManager().closeSession(getAuthentication());
         //getIsisInteractionFactory().closeSessionStack();
-        
+
         super.invalidateNow();
-        
+
     }
 
     @Override
@@ -141,10 +141,10 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
     }
 
     public synchronized Authentication getAuthentication() {
-        
+
         commonContext.getInteractionTracker().currentAuthentication()
         .ifPresent(currentAuthentication->{
-            
+
             if (getAuthenticationManager().isSessionValid(currentAuthentication)) {
                 if (this.authentication != null) {
                     if (Objects.equals(currentAuthentication.getUserName(), this.authentication.getUserName())) {
@@ -172,7 +172,7 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
                     this.authentication = currentAuthentication;
                 }
             }
-            
+
         });
 
         return this.authentication;
@@ -180,8 +180,8 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
 
     /**
      * This is a no-op if the {@link #getAuthentication() authentication session}'s
-     * {@link Authentication#getType() type} is 
-     * {@link org.apache.isis.core.security.authentication.Authentication.Type#EXTERNAL external} 
+     * {@link Authentication#getType() type} is
+     * {@link org.apache.isis.core.security.authentication.Authentication.Type#EXTERNAL external}
      * (eg as managed by keycloak).
      */
     public void invalidate() {
@@ -247,12 +247,12 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
         val sessionLoggingServices = getSessionLoggingServices();
 
         final Runnable loggingTask = ()->{
-            
+
             val now = virtualClock().javaUtilDate();
-            
+
             // use hashcode as session identifier, to avoid re-binding http sessions if using Session#getId()
             int sessionHashCode = System.identityHashCode(AuthenticatedWebSessionForIsis.this);
-            sessionLoggingServices.forEach(sessionLoggingService -> 
+            sessionLoggingServices.forEach(sessionLoggingService ->
                 sessionLoggingService.log(type, username, now, causedBy, Integer.toString(sessionHashCode))
             );
         };
@@ -267,7 +267,7 @@ implements BreadcrumbModelProvider, BookmarkedPagesModelProvider, HasCommonConte
     protected Can<SessionLoggingService> getSessionLoggingServices() {
         return commonContext.getServiceRegistry().select(SessionLoggingService.class);
     }
-    
+
     protected InteractionFactory getIsisInteractionFactory() {
         return commonContext.lookupServiceElseFail(InteractionFactory.class);
     }
diff --git a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
index b5fd147..4a02d66 100644
--- a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
+++ b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_Authenticate.java
@@ -46,7 +46,7 @@ import org.apache.isis.core.security.authentication.AuthenticationRequest;
 import org.apache.isis.core.security.authentication.AuthenticationRequestPassword;
 import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
 import org.apache.isis.core.security.authentication.singleuser.SingleUserAuthentication;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 import org.apache.isis.core.security.authentication.standard.RandomCodeGeneratorDefault;
 
 public class AuthenticatedWebSessionForIsis_Authenticate {
@@ -84,16 +84,16 @@ public class AuthenticatedWebSessionForIsis_Authenticate {
 
                 allowing(mockCommonContext).getInteractionTracker();
                 will(returnValue(mockIsisInteractionTracker));
-                
+
                 allowing(mockIsisInteractionTracker).currentAuthentication();
                 will(returnValue(Optional.of(new SingleUserAuthentication())));
-                
+
                 allowing(mockIsisInteractionFactory)
                 .runAuthenticated(with(new SingleUserAuthentication()), with(any(ThrowingRunnable.class)));
-                
+
                 allowing(mockIsisInteractionFactory)
                 .runAnonymous(with(any(ThrowingRunnable.class)));
-                
+
                 // ignore
 
                 // must provide explicit expectation, since Locale is final.
@@ -152,9 +152,9 @@ public class AuthenticatedWebSessionForIsis_Authenticate {
                 will(returnValue(null));
             }
         });
-        
+
         setupWebSession();
-        
+
         assertThat(webSession.authenticate("jsmith", "secret"), is(false));
         assertThat(webSession.getAuthentication(), is(nullValue()));
     }
diff --git a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
index ef78673..73e96dc 100644
--- a/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
+++ b/viewers/wicket/viewer/src/test/java/org/apache/isis/viewer/wicket/viewer/integration/AuthenticatedWebSessionForIsis_SignIn.java
@@ -43,7 +43,7 @@ import org.apache.isis.core.security.authentication.AuthenticationRequest;
 import org.apache.isis.core.security.authentication.AuthenticationRequestPassword;
 import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
 import org.apache.isis.core.security.authentication.singleuser.SingleUserAuthentication;
-import org.apache.isis.core.security.authentication.standard.Authenticator;
+import org.apache.isis.core.security.authentication.Authenticator;
 import org.apache.isis.core.security.authentication.standard.RandomCodeGeneratorDefault;
 
 public class AuthenticatedWebSessionForIsis_SignIn {
@@ -82,10 +82,10 @@ public class AuthenticatedWebSessionForIsis_SignIn {
 
                 allowing(mockIsisInteractionFactory)
                 .runAuthenticated(with(new SingleUserAuthentication()), with(any(ThrowingRunnable.class)));
-                
+
                 allowing(mockIsisInteractionFactory)
                 .runAnonymous(with(any(ThrowingRunnable.class)));
-                
+
                 // ignore
 
                 // must provide explicit expectation, since Locale is final.