You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/12/05 10:11:52 UTC

[isis] branch master updated: ISIS-2464: more renaming, sync adoc

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 3b8f1b4  ISIS-2464: more renaming, sync adoc
3b8f1b4 is described below

commit 3b8f1b4f11095a16cc367fa9766907cc94a1f30f
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Dec 5 11:04:28 2020 +0100

    ISIS-2464: more renaming, sync adoc
---
 .../applib-classes/examples/clock/Clock.java       | 153 ------------
 .../examples/clock/VirtualClock.java               | 175 ++++++++++++++
 .../examples/clock/VirtualClock_frozen.java        |  66 ++++++
 .../examples/clock/VirtualClock_system.java        |  57 +++++
 .../examples/clock/VirtualClock_withOffset.java    |  70 ++++++
 .../examples/clock/package-info.java               |  42 ----
 .../examples/services/clock/ClockService.java      | 105 ++++-----
 .../examples/services/iactn/ExecutionContext.java  |  83 +++++++
 .../examples/services/iactn/Interaction.java       | 257 +--------------------
 .../examples/services/sudo/SudoService.java        |  83 +++----
 .../examples/services/user/RoleMemento.java        |   9 +-
 .../examples/services/user/UserMemento.java        | 184 +++++++++++----
 .../examples/services/user/UserService.java        |  44 +++-
 .../services/wrapper/control/AsyncControl.java     |  54 +++--
 .../modules/config/pages/sections/resteasy.adoc    |   2 +-
 .../session/InteractionFactoryDefault.java         |   4 +-
 .../wrapper/WrapperFactoryDefault.java             |   8 +-
 .../manager/AuthenticationManager.java             |   8 +-
 .../secondary/job/ReplicateAndReplayJob.java       |  12 +-
 .../adoc/modules/quartz/examples/DemoJob.java      |   2 +-
 .../vaadin/ui/auth/AuthSessionStoreUtil.java       |   8 +-
 .../viewer/vaadin/ui/auth/LogoutHandlerVaa.java    |   6 +-
 .../ui/auth/VaadinAuthenticationHandler.java       |  16 +-
 .../viewer/vaadin/viewer/IsisServletForVaadin.java |  12 +-
 .../ROOT/partials/security/user-registration.adoc  |   6 +-
 .../modules/ROOT/partials/security/web-xml.adoc    |   4 +-
 .../IsisRestfulObjectsInteractionFilter.java       |  10 +-
 .../webmodule/auth/AuthenticationStrategy.java     |   4 +-
 .../auth/AuthenticationStrategyBasicAuth.java      |   2 +-
 .../auth/AuthenticationStrategyDefault.java        |  14 +-
 30 files changed, 823 insertions(+), 677 deletions(-)

diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/Clock.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/Clock.java
deleted file mode 100644
index 37ec6a4..0000000
--- a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/Clock.java
+++ /dev/null
@@ -1,153 +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.applib.clock;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.OffsetDateTime;
-import java.time.ZoneId;
-import java.util.Date;
-
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-
-import lombok.val;
-
-/**
- * Provides a mechanism to get (and possible to set) the current time.
- *
- * <p>
- * The clock is used primarily by the temporal value classes, and is accessed by
- * the NOF as a singleton. The actual implementation used can be configured at
- * startup, but once specified the clock instance cannot be changed.
- *
- * <p>
- * Unless another {@link Clock} implementation has been installed, the first
- * call to {@link #getInstance()} will instantiate an implementation that just
- * uses the system's own clock. Alternate implementations can be created via
- * suitable subclasses, but this must be done <b><i>before</i></b> the first
- * call to {@link #getInstance()}. 
- */
-public abstract class Clock {
-    
-    protected static Clock instance;
-
-    /**
-     * Returns the (singleton) instance of {@link Clock}.
-     *
-     * <p>
-     * Unless it has been otherwise created, will lazily instantiate an
-     * implementation that just delegate to the computer's own system clock (as
-     * per {@link System#currentTimeMillis()}.
-     *
-     * @return
-     */
-    public static final Clock getInstance() {
-        if (!isInitialized()) {
-            instance = new SystemClock();
-        }
-        return instance;
-    }
-
-    /**
-     * Whether has been initialized or not.
-     */
-    public static boolean isInitialized() {
-        return instance != null;
-    }
-
-    /**
-     * The time as the number of milliseconds since the epoch start. (UTC)
-     *
-     * @see Date#getTime()
-     */
-    public static long getEpochMillis() {
-        return getInstance().now().toEpochMilli();
-    }
-
-    public static LocalDate getTimeAsLocalDate() {
-        return getTimeAsLocalDateTime().toLocalDate();
-    }
-
-    public static LocalDateTime getTimeAsLocalDateTime() {
-        val zoneId = ZoneId.systemDefault();
-        return LocalDateTime.ofInstant(getInstance().now(), zoneId);
-    }
-
-    /**
-     * Returns the time as {@link OffsetDateTime},
-     * using the {@link ZoneId#systemDefault() system default} timezone.
-     */
-    public static OffsetDateTime getTimeAsOffsetDateTime() {
-        val zoneId = ZoneId.systemDefault();
-        return OffsetDateTime.ofInstant(getInstance().now(), zoneId);
-    }
-
-
-    public static Timestamp getTimeAsJavaSqlTimestamp() {
-        return new java.sql.Timestamp(getEpochMillis());
-    }
-
-    /**
-     * Returns the time as a Joda {@link DateTime},
-     * using the {@link ZoneId#systemDefault() system default} timezone.
-     */
-    public static DateTime getTimeAsJodaDateTime() {
-        final ZoneId zoneId = ZoneId.systemDefault();
-        return new DateTime(getInstance().now().toEpochMilli(), DateTimeZone.forID(zoneId.getId()));
-    }
-
-    /**
-     * Allows subclasses to remove their implementation.
-     *
-     * @return whether a clock was removed.
-     */
-    protected static boolean remove() {
-        if (instance == null) {
-            return false;
-        }
-        instance = null;
-        return true;
-    }
-
-    protected Clock() {
-        instance = this;
-    }
-
-
-    /**
-     * The current time represented by an instant, either measured or simulated.
-     */
-    protected abstract Instant now();
-
-
-}
-
-final class SystemClock extends Clock {
-
-    SystemClock() {}
-    
-    @Override
-    protected Instant now() {
-        return Instant.now();
-    }
-
-}
diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock.java
new file mode 100644
index 0000000..6a863f3
--- /dev/null
+++ b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock.java
@@ -0,0 +1,175 @@
+/*
+ *  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.applib.clock;
+
+import java.io.Serializable;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import org.apache.isis.applib.jaxb.JavaSqlXMLGregorianCalendarMarshalling;
+import org.apache.isis.applib.services.iactn.Interaction;
+
+import lombok.NonNull;
+import lombok.val;
+
+/**
+ * Works in connection with {@link InteractionFactory}, such that it allows an {@link Interaction}
+ * to run with its own simulated (or actual) time. 
+ * <p>
+ * Relates to {@link VirtualContext}
+ * 
+ * @since 2.0
+ *
+ */
+@FunctionalInterface
+public interface VirtualClock extends Serializable {
+    
+    // -- INTERFACE
+    
+    /**
+     * Returns the (virtual) time as an {@link Instant}.
+     * 
+     * @apiNote This is a universal time difference, that does not depend on 
+     * where you are (eg. your current timezone), just on when you are. 
+     *
+     * @see {@link Instant}
+     */
+    Instant now();
+    
+    // -- FACTORIES
+    
+    /**
+     * Returns a the system's default ticking clock.
+     */
+    static VirtualClock system() {
+        return new VirtualClock_system();
+    }
+    
+    /**
+     * Returns a ticking clock set to virtual time {@link Instant} {@code virtualNow}
+     */
+    static VirtualClock nowAt(@NonNull Instant virtualNow) {
+        // positive if the resulting clock is in the future
+        val offsetMillis = ChronoUnit.MILLIS.between(Instant.now(), virtualNow);
+        return new VirtualClock_withOffset(offsetMillis);
+    }
+    
+    /**
+     * Always returns the time {@link Instant} as given by {@code frozenAt}
+     */
+    static VirtualClock frozenAt(@NonNull Instant frozenAt) {
+        return new VirtualClock_frozen(frozenAt);
+    }
+    
+    /**
+     * Always returns the time {@link Instant} 2003/8/17 21:30:25 (UTC)
+     */
+    static VirtualClock frozenTestClock() {
+        val frozenAt = Instant.from(
+                ZonedDateTime.of(2003, 7, 17, 21, 30, 25, 0, ZoneId.from(ZoneOffset.UTC)));
+        return frozenAt(frozenAt);
+    }
+    
+    // -- UTILITY
+    
+    /**
+     * Returns the (virtual) time as the number of milliseconds since the epoch start.
+     * 
+     * @apiNote This is a universal time difference, that does not depend on 
+     * where you are (eg. your current timezone), just on when you are. 
+     *
+     * @see {@link Instant}
+     */
+    default long getEpochMillis() {
+        return now().toEpochMilli();
+    }
+
+    /**
+     * Returns the (virtual) time as {@link LocalDate}, using the {@link ZoneId} timezone.
+     * @param zoneId - the time-zone, which may be an offset, not null
+     */
+    default LocalDate localDate(final @NonNull ZoneId zoneId) {
+        return localDateTime(zoneId).toLocalDate();
+    }
+
+    /**
+     * Returns the (virtual) time as {@link LocalDateTime}, using the {@link ZoneId} timezone.
+     * @param zoneId - the time-zone, which may be an offset, not null
+     */
+    default LocalDateTime localDateTime(final @NonNull ZoneId zoneId) {
+        return LocalDateTime.ofInstant(now(), zoneId);
+    }
+
+    /**
+     * Returns the (virtual) time as {@link OffsetDateTime}, using the {@link ZoneId} timezone.
+     * @param zoneId - the time-zone, which may be an offset, not null
+     */
+    default OffsetDateTime offsetDateTime(final @NonNull ZoneId zoneId) {
+        return OffsetDateTime.ofInstant(now(), zoneId);
+    }
+
+    default java.util.Date javaUtilDate() {
+        return new java.util.Date(getEpochMillis());
+    }
+    
+    default java.sql.Timestamp javaSqlTimestamp() {
+        return new java.sql.Timestamp(getEpochMillis());
+    }
+    
+    default XMLGregorianCalendar xmlGregorianCalendar() {
+        return JavaSqlXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(javaSqlTimestamp());
+    }
+
+    // -- DEPRECATIONS
+    
+    /**
+     * Returns the time as a Joda {@link org.joda.time.DateTime},
+     * using the {@link ZoneId#systemDefault() system default} timezone.
+     * @deprecated please migrate to java.time.*
+     */
+    @Deprecated
+    default org.joda.time.DateTime asJodaDateTime(final @NonNull ZoneId zoneId) {
+        return new org.joda.time.DateTime(getEpochMillis(), DateTimeZone.forID(zoneId.getId()));
+    }
+    
+    /**
+     * Returns the time as a Joda {@link DateTime},
+     * using the {@link ZoneId#systemDefault() system default} timezone.
+     * @deprecated please migrate to java.time.*
+     */
+    @Deprecated
+    default org.joda.time.LocalDate asJodaLocalDate(final @NonNull ZoneId zoneId) {
+        return new org.joda.time.LocalDate(getEpochMillis(), DateTimeZone.forID(zoneId.getId()));
+    }
+
+    
+
+
+}
diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_frozen.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_frozen.java
new file mode 100644
index 0000000..b01229e
--- /dev/null
+++ b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_frozen.java
@@ -0,0 +1,66 @@
+/*
+ *  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.applib.clock;
+
+import java.time.Instant;
+import java.util.Objects;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+final class VirtualClock_frozen implements VirtualClock {
+
+    private static final long serialVersionUID = -2589204298085221985L;
+    
+    private final Instant frozenInstant;
+    
+    @Override
+    public Instant now() {
+        return frozenInstant;
+    }
+    
+    // -- TO STRING, EQUALS, HASHCODE
+    
+    @Override
+    public String toString() {
+        return String.format("%s: %s", this.getClass().getSimpleName(), xmlGregorianCalendar());
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if(obj==null) {
+            return false;
+        }
+        // equal if same class and same frozenInstant
+        if(!Objects.equals(this.getClass(), obj.getClass())) {
+            return false;
+        }
+        if(!Objects.equals(this.frozenInstant, ((VirtualClock_frozen)obj).frozenInstant)) {
+            return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        // equal if same class and same frozenInstant
+        return Objects.hash(this.getClass(), frozenInstant);
+    }
+
+}
diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_system.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_system.java
new file mode 100644
index 0000000..215eb4c
--- /dev/null
+++ b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_system.java
@@ -0,0 +1,57 @@
+/*
+ *  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.applib.clock;
+
+import java.time.Instant;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+final class VirtualClock_system implements VirtualClock {
+
+    private static final long serialVersionUID = 4019699893189814294L;
+
+    @Override
+    public Instant now() {
+        return Instant.now();
+    }
+
+    // -- TO STRING, EQUALS, HASHCODE
+    
+    @Override
+    public String toString() {
+        return String.format("%s: %s", this.getClass().getSimpleName(), xmlGregorianCalendar());
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if(obj==null) {
+            return false;
+        }
+        // equal if same class
+        return this.getClass().equals(obj.getClass());
+    }
+    
+    @Override
+    public int hashCode() {
+        // equal if same class
+        return this.getClass().hashCode();
+    }
+
+}
diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_withOffset.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_withOffset.java
new file mode 100644
index 0000000..9f4df40
--- /dev/null
+++ b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/VirtualClock_withOffset.java
@@ -0,0 +1,70 @@
+/*
+ *  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.applib.clock;
+
+import java.time.Instant;
+import java.util.Objects;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+final class VirtualClock_withOffset implements VirtualClock {
+
+    private static final long serialVersionUID = -2589204298085221985L;
+    
+    /**
+     * Amount of time (milli seconds) this clock is offset into the future 
+     * with respect to the actual (system) time.
+     */
+    private final long millisOffset;
+    
+    @Override
+    public Instant now() {
+        return Instant.now().plusMillis(millisOffset);
+    }
+    
+    // -- TO STRING, EQUALS, HASHCODE
+    
+    @Override
+    public String toString() {
+        return String.format("%s: %s", this.getClass().getSimpleName(), xmlGregorianCalendar());
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if(obj==null) {
+            return false;
+        }
+        // equal if same class and same millisOffset
+        if(!Objects.equals(this.getClass(), obj.getClass())) {
+            return false;
+        }
+        if(!Objects.equals(this.millisOffset, ((VirtualClock_withOffset)obj).millisOffset)) {
+            return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        // equal if same class and same millisOffset
+        return Objects.hash(this.getClass(), millisOffset);
+    }
+
+}
diff --git a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/package-info.java b/api/applib/src/main/adoc/modules/applib-classes/examples/clock/package-info.java
deleted file mode 100644
index 4bb4e71..0000000
--- a/api/applib/src/main/adoc/modules/applib-classes/examples/clock/package-info.java
+++ /dev/null
@@ -1,42 +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.
- */
-
-/**
- * Defines a {@link org.apache.isis.applib.clock.Clock} singleton
- * that can be used to obtain the current time.
- *
- * <p>
- * All of the built-in value types relating to time have
- * {@link org.apache.isis.applib.adapters.ValueSemanticsProvider#getDefaultsProvider() defaults}
- * that use the {@link org.apache.isis.applib.clock.Clock} singleton.  For
- * consistency, domain objects and services should also use the Clock.
- *
- * <p>
- * Providing a clock is useful for testing, allowing the "current" time
- * to be placed under programmatic control (by {@link org.apache.isis.applib.fixtures.FixtureClock#initialize() initializing}
- * a {@link org.apache.isis.applib.fixtures.FixtureClock}.  Otherwise though
- * the {@link org.apache.isis.applib.clock.Clock} just uses the time from the
- * current system.
- *
- * <p>
- * Note: this design also means that other {@link org.apache.isis.applib.clock.Clock}
- * implementations - such as a one that accesses the time from an NNTP time
- * daemon - could also be used.
- */
-package org.apache.isis.applib.clock;
\ No newline at end of file
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/clock/ClockService.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/clock/ClockService.java
index 4583a4c..216d605 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/clock/ClockService.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/clock/ClockService.java
@@ -18,71 +18,62 @@
  */
 package org.apache.isis.applib.services.clock;
 
-import java.util.TimeZone;
-
-import javax.inject.Named;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import org.joda.time.DateTimeZone;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Primary;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.clock.Clock;
-import org.apache.isis.applib.jaxb.JavaSqlXMLGregorianCalendarMarshalling;
+import org.apache.isis.applib.clock.VirtualClock;
 
 /**
- * This service allows an application to be decoupled from the system time.  The most common use case is in support of
- * testing scenarios, to &quot;mock the clock&quot;.  Use of this service also opens up the use of centralized
+ * This service allows an application to be decoupled from the system time.  
+ * The most common use case is in support of testing scenarios, to &quot;mock the clock&quot;.  
+ * Use of this service also opens up the use of centralized
  * co-ordinated time management through a centralized time service.
  *
  */
 // tag::refguide[]
-@Service
-@Named("isisApplib.ClockService")
-@Order(OrderPrecedence.MIDPOINT)
-@Primary
-@Qualifier("Default")
-public class ClockService {
-
-    public java.time.LocalDate now() {
-        return Clock.getTimeAsLocalDate();
-    }
-
-    public java.time.LocalDateTime nowAsLocalDateTime() {
-        return Clock.getTimeAsLocalDateTime();
-    }
-
-    public java.time.OffsetDateTime nowAsOffsetDateTime() {
-        return Clock.getTimeAsOffsetDateTime();
-    }
-
-    public java.sql.Timestamp nowAsJavaSqlTimestamp() {
-        return Clock.getTimeAsJavaSqlTimestamp();
-    }
-
-    public XMLGregorianCalendar nowAsXMLGregorianCalendar() {
-        return JavaSqlXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(nowAsJavaSqlTimestamp());
-    }
-
-    public long nowAsMillis() {
-        return Clock.getEpochMillis();
-    }
-
-    public java.util.Date nowAsJavaUtilDate() {
-        return new java.util.Date(nowAsMillis());
-    }
-
-    public org.joda.time.DateTime nowAsJodaDateTime() {
-        return Clock.getTimeAsJodaDateTime();
-    }
+public interface ClockService {
 
-    public org.joda.time.LocalDate nowAsJodaLocalDate() {
-        final DateTimeZone timeZone = DateTimeZone.forTimeZone(TimeZone.getDefault());
-        return new org.joda.time.LocalDate(nowAsMillis(), timeZone);
+    VirtualClock getClock();
+    
+    // -- SHORTCUTS
+    
+    default long getEpochMillis() {
+        return getClock().getEpochMillis();
     }
+    
+//    public java.time.LocalDate now() {
+//        return Clock.getTimeAsLocalDate();
+//    }
+//
+//    public java.time.LocalDateTime nowAsLocalDateTime() {
+//        return Clock.getTimeAsLocalDateTime();
+//    }
+//
+//    public java.time.OffsetDateTime nowAsOffsetDateTime() {
+//        return Clock.getTimeAsOffsetDateTime();
+//    }
+//
+//    public java.sql.Timestamp nowAsJavaSqlTimestamp() {
+//        return Clock.getTimeAsJavaSqlTimestamp();
+//    }
+//
+//    public XMLGregorianCalendar nowAsXMLGregorianCalendar() {
+//        return JavaSqlXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(nowAsJavaSqlTimestamp());
+//    }
+//
+//    public long nowAsMillis() {
+//        return Clock.getEpochMillis();
+//    }
+//
+//    public java.util.Date nowAsJavaUtilDate() {
+//        return new java.util.Date(nowAsMillis());
+//    }
+//
+//    public org.joda.time.DateTime nowAsJodaDateTime() {
+//        return Clock.getTimeAsJodaDateTime();
+//    }
+//
+//    public org.joda.time.LocalDate nowAsJodaLocalDate() {
+//        final DateTimeZone timeZone = DateTimeZone.forTimeZone(TimeZone.getDefault());
+//        return new org.joda.time.LocalDate(nowAsMillis(), timeZone);
+//    }
 
 }
 // end::refguide[]
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/ExecutionContext.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/ExecutionContext.java
new file mode 100644
index 0000000..2265b69
--- /dev/null
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/ExecutionContext.java
@@ -0,0 +1,83 @@
+/*
+ *  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.applib.services.iactn;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.isis.applib.clock.VirtualClock;
+import org.apache.isis.applib.services.user.UserMemento;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.Value;
+import lombok.With;
+
+/**
+ * Provides the user and scenario specific environment for an {@link Interaction.Execution}
+ * 
+ * @since 2.0
+ */
+@Value @Builder
+@RequiredArgsConstructor
+public final class ExecutionContext implements Serializable {
+    
+    private static final long serialVersionUID = -220896735209733865L;
+    
+    // -- IMMUTABLE FIELDS
+
+    /**
+     * The (programmatically) simulated (or actual) user.
+     * 
+     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its 
+     * own simulated (or actual) user 
+     */
+    @With @Getter @Builder.Default 
+    private final @NonNull UserMemento user = UserMemento.system();
+    
+    /**
+     * The (programmatically) simulated (or actual) clock.
+     * 
+     * @apiNote immutable, allows an {@link Interaction} to (logically) run with its 
+     * own simulated (or actual) clock 
+     */
+    @With @Getter @Builder.Default 
+    private final @NonNull VirtualClock clock = VirtualClock.system();
+    
+    @With @Getter @Builder.Default 
+    private final @NonNull Locale locale = Locale.getDefault();
+    
+    @With @Getter @Builder.Default 
+    private final @NonNull TimeZone timeZone = TimeZone.getDefault();
+    
+    // -- FACTORIES
+    
+    /**
+     * Creates a new {@link ExecutionContext} with the specified user and 
+     * system defaults for clock, locale and time-zone.
+     */
+    public static ExecutionContext ofUserWithSystemDefaults(
+            final @NonNull UserMemento user) {
+        return new ExecutionContext(user, VirtualClock.system(), Locale.getDefault(), TimeZone.getDefault());
+    }   
+    
+}
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/Interaction.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/Interaction.java
index 5e0f9c7..906c194 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/Interaction.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/iactn/Interaction.java
@@ -22,10 +22,6 @@ package org.apache.isis.applib.services.iactn;
 import java.sql.Timestamp;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.LongAdder;
 
 import org.apache.isis.applib.events.domain.AbstractDomainEvent;
 import org.apache.isis.applib.events.domain.ActionDomainEvent;
@@ -39,7 +35,6 @@ import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.applib.util.schema.MemberExecutionDtoUtils;
 import org.apache.isis.commons.having.HasUniqueId;
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.schema.common.v2.DifferenceDto;
 import org.apache.isis.schema.common.v2.InteractionType;
 import org.apache.isis.schema.common.v2.PeriodDto;
@@ -50,9 +45,7 @@ import org.apache.isis.schema.ixn.v2.ObjectCountsDto;
 import org.apache.isis.schema.ixn.v2.PropertyEditDto;
 
 import lombok.Getter;
-import lombok.NonNull;
 import lombok.val;
-import lombok.extern.log4j.Log4j2;
 
 /**
  * Represents an action invocation or property modification, resulting in some state change of the system.  It captures
@@ -80,245 +73,26 @@ import lombok.extern.log4j.Log4j2;
  *
  */
 // tag::refguide[]
-@Log4j2
-public class Interaction implements HasUniqueId {
+public interface Interaction extends HasUniqueId {
 
-    public Interaction(final @NonNull UUID uniqueId) {
-        this.command = new Command(uniqueId);
-    }
-
-    @Getter
-    private final Command command;                  // <.>
-
-    @Override
-    public UUID getUniqueId() {                     // <.>
-        return command.getUniqueId();
-    }
+    Command getCommand();                  // <.>
 
     // end::refguide[]
-    private final List<Execution<?,?>> executionGraphs = _Lists.newArrayList();
-
-    /**
-     * Returns a (list of) {@link Execution}s in the order that they were pushed.  Generally there will be just one entry in this list, but additional entries may arise from the use of mixins/contributions when re-rendering a modified object.
-     *
-     * <p>
-     *     Each {@link Execution} represents a call stack of domain events (action invocations or property edits),
-     *     that may in turn cause other domain events to be fired (by virtue of the {@link WrapperFactory}).
-     *     The reason that a list is returned is to support bulk command/actions (against multiple targets).  A non-bulk
-     *     action will return a list of just one element.
-     * </p>
-     *
-     * @implNote - it seems that this is never actually called.
-     *  The PropertyEdit/ActionInvocation facet diligently calls
-     *  {@link #execute(MemberExecutor, PropertyEdit, ClockService, MetricsService)} or
-     *  {@link #execute(MemberExecutor, ActionInvocation, ClockService, MetricsService)} for us, to ensure that the
-     *  graph is populated, but then delegate to the PublisherService immediately at the end... ie {@link org.apache.isis.schema.ixn.v2.InteractionDto}s are published as we go, not all in a batch at the end.
-     */
-    // tag::refguide[]
-    public List<Execution<?,?>> getExecutions() {   // <.>
-        // end::refguide[]
 
-        return Collections.unmodifiableList(executionGraphs);
-
-        // tag::refguide[]
-        // ...
-    }
-
-    // end::refguide[]
     /**
      * The current (most recently pushed) {@link Execution}.
      */
     // tag::refguide[]
-    @Getter
-    private Execution<?,?> currentExecution;        // <.>
+    Execution<?,?> getCurrentExecution();        // <.>
 
     // end::refguide[]
     /**
      * The execution that preceded the current one.
      */
     // tag::refguide[]
-    @Getter
-    private Execution<?,?> priorExecution;          // <.>
+    Execution<?,?> getPriorExecution();          // <.>
 
     // end::refguide[]
-    /**
-     * <b>NOT API</b>: intended to be called only by the framework.
-     *
-     * Clears the set of {@link Execution}s that may have been {@link #push(Execution)}ed.
-     */
-    public void clear() {
-        executionGraphs.clear();
-    }
-
-    /**
-     * <b>NOT API</b>: intended only to be implemented by the framework.
-     *
-     * <p>
-     * (Modelled after {@link Callable}), is the implementation
-     * by which the framework actually performs the interaction.
-     */
-    public interface MemberExecutor<T extends Execution<?,?>> {
-        Object execute(final T currentExecution);
-    }
-
-    /**
-     * <b>NOT API</b>: intended to be called only by the framework.
-     *
-     * <p>
-     * Use the provided {@link MemberExecutor} to invoke an action, with the provided
-     * {@link ActionInvocation} capturing the details of said action.
-     * </p>
-     *
-     * <p>
-     *     Because this both pushes an {@link Interaction.Execution} to
-     *     represent the action invocation and then pops it, that completed
-     *     execution is accessible at {@link Interaction#getPriorExecution()}.
-     * </p>
-     */
-    public Object execute(
-            final MemberExecutor<ActionInvocation> memberExecutor,
-            final ActionInvocation actionInvocation,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final Command command) {
-
-        pushAndStart(actionInvocation, clockService, metricsService, command);
-        try {
-            return executeInternal(memberExecutor, actionInvocation);
-        } finally {
-            popAndComplete(clockService, metricsService);
-        }
-    }
-
-    private void pushAndStart(ActionInvocation actionInvocation, ClockService clockService, MetricsService metricsService, Command command) {
-        push(actionInvocation);
-        start(actionInvocation, clockService, metricsService, command);
-    }
-
-    /**
-     * <b>NOT API</b>: intended to be called only by the framework.
-     *
-     * <p>
-     * Use the provided {@link MemberExecutor} to edit a property, with the provided
-     * {@link PropertyEdit} capturing the details of said property edit.
-     * </p>
-     *
-     * <p>
-     *     Because this both pushes an {@link Interaction.Execution} to
-     *     represent the property edit and then pops it, that completed
-     *     execution is accessible at {@link Interaction#getPriorExecution()}.
-     * </p>
-     */
-    public Object execute(
-            final MemberExecutor<PropertyEdit> memberExecutor,
-            final PropertyEdit propertyEdit,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final Command command) {
-
-        push(propertyEdit);
-        start(propertyEdit, clockService, metricsService, command);
-        try {
-            return executeInternal(memberExecutor, propertyEdit);
-        } finally {
-            popAndComplete(clockService, metricsService);
-        }
-    }
-
-    private <T extends Execution<?,?>> Object executeInternal(MemberExecutor<T> memberExecutor, T execution) {
-
-        try {
-            Object result = memberExecutor.execute(execution);
-            execution.setReturned(result);
-            return result;
-        } catch (Exception ex) {
-
-            //TODO there is an issue with exceptions getting swallowed, unless this is fixed,
-            // we rather print all of them, no matter whether recognized or not later on
-            // examples are IllegalArgument- or NullPointer- exceptions being swallowed when using the
-            // WrapperFactory utilizing async calls
-            log.error("failed to execute an interaction", ex);
-
-            // just because an exception has thrown, does not mean it is that significant;
-            // it could be that it is recognized by an ExceptionRecognizer and is not severe
-            // eg. unique index violation in the DB
-            getCurrentExecution().setThrew(ex);
-
-            // propagate (as in previous design); caller will need to trap and decide
-            throw ex;
-        }
-    }
-
-
-    /**
-     * <b>NOT API</b>: intended to be called only by the framework.
-     *
-     * <p>
-     * Push a new {@link org.apache.isis.applib.events.domain.AbstractDomainEvent}
-     * onto the stack of events held by the command.
-     * </p>
-     */
-    private Execution<?,?> push(final Execution<?,?> execution) {
-
-        if(currentExecution == null) {
-            // new top-level execution
-            executionGraphs.add(execution);
-
-        } else {
-            // adds to graph of parent
-            execution.setParent(currentExecution);
-        }
-
-
-        // update this.currentExecution and this.previousExecution
-        moveCurrentTo(execution);
-
-        return execution;
-    }
-
-    private void start(
-            final Interaction.Execution<?,?> execution,
-            final ClockService clockService,
-            final MetricsService metricsService,
-            final Command command) {
-        // set the startedAt (and update command if this is the top-most member execution)
-        // (this isn't done within Interaction#execute(...) because it requires the DTO
-        // to have been set on the current execution).
-        val startedAt = execution.start(clockService, metricsService);
-        if(command.getStartedAt() == null) {
-            command.updater().setStartedAt(startedAt);
-        }
-    }
-
-    /**
-     * <b>NOT API</b>: intended to be called only by the framework.
-     *
-     * <p>
-     * Pops the top-most  {@link org.apache.isis.applib.events.domain.ActionDomainEvent}
-     * from the stack of events held by the command.
-     * </p>
-     */
-    private Execution<?,?> popAndComplete(
-            final ClockService clockService,
-            final MetricsService metricsService) {
-
-        if(currentExecution == null) {
-            throw new IllegalStateException("No current execution to pop");
-        }
-        final Execution<?,?> popped = currentExecution;
-
-        final Timestamp completedAt = clockService.nowAsJavaSqlTimestamp();
-        popped.setCompletedAt(completedAt, metricsService);
-
-        moveCurrentTo(currentExecution.getParent());
-        return popped;
-    }
-
-    private void moveCurrentTo(final Execution<?,?> newExecution) {
-        priorExecution = currentExecution;
-        currentExecution = newExecution;
-    }
-
 
     /**
      * Enumerates the different reasons why multiple occurrences of a certain type might occur within a single
@@ -361,8 +135,6 @@ public class Interaction implements HasUniqueId {
     }
     // end::refguide-1[]
 
-    private final Map<String, LongAdder> maxBySequence = _Maps.newHashMap();
-
     /**
      * Generates numbers in a named sequence.
      *
@@ -370,23 +142,10 @@ public class Interaction implements HasUniqueId {
      * generate sequence numbers corresponding to the sequences enumerated by the {@link Sequence} enum.
      */
     // tag::refguide[]
-    public int next(final String sequenceId) {      // <.>
-        // end::refguide[]
-
-        final LongAdder adder = maxBySequence.computeIfAbsent(sequenceId, this::newAdder);
-        adder.increment();
-        return adder.intValue();
-
-        // tag::refguide[]
-        // ...
-    }
+    int next(final String sequenceId);      // <.>
+    
     // end::refguide[]
 
-    private LongAdder newAdder(String ignore) {
-        final LongAdder adder = new LongAdder();
-        adder.decrement();
-        return adder;
-    }
 
     /**
      * Represents an action invocation/property edit as a node in a call-stack execution graph, with sub-interactions
@@ -532,7 +291,7 @@ public class Interaction implements HasUniqueId {
                 final MetricsService metricsService) {
             // end::refguide-2[]
 
-            val startedAt = clockService.nowAsJavaSqlTimestamp();
+            val startedAt = clockService.getClock().javaSqlTimestamp();
             syncMetrics(When.BEFORE, startedAt, metricsService);
             return startedAt;
 
@@ -544,7 +303,7 @@ public class Interaction implements HasUniqueId {
         /**
          * <b>NOT API</b>: intended to be called only by the framework.
          */
-        void setCompletedAt(
+        public void setCompletedAt(
                 final Timestamp completedAt,
                 final MetricsService metricsService) {
             syncMetrics(When.AFTER, completedAt, metricsService);
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/sudo/SudoService.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/sudo/SudoService.java
index 621828b..edff67b 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/sudo/SudoService.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/sudo/SudoService.java
@@ -16,14 +16,17 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.apache.isis.applib.services.sudo;
 
-import java.util.List;
-import java.util.function.Supplier;
+import java.util.concurrent.Callable;
+import java.util.function.UnaryOperator;
 
+import org.apache.isis.applib.services.iactn.ExecutionContext;
+import org.apache.isis.applib.services.user.RoleMemento;
 import org.apache.isis.applib.services.user.UserService;
 
+import lombok.NonNull;
+
 /**
  * Intended only for use by fixture scripts and integration tests, allows a block of code to execute
  * while the {@link UserService}'s {@link UserService#getUser() getUser()} method returns the specified user/role
@@ -37,75 +40,49 @@ public interface SudoService {
      * If included in the list of roles, then will disable security checks (can view and use all object members).
      */
     // tag::refguide[]
-    String ACCESS_ALL_ROLE =                                // <.>
-            SudoService.class.getName() + "#accessAll";
+    RoleMemento ACCESS_ALL_ROLE =                                // <.>
+            new RoleMemento(
+                    SudoService.class.getName() + "#accessAll",
+                    "Sudo, can view and use all object members.");
+            
 
     // end::refguide[]
     /**
      * Executes the supplied block, with the {@link UserService} returning the specified user.
-     *
-     * <p>
-     *    The roles of this user will be the same as the currently logged-in user.
-     * </p>
+     * @param sudoMapper - maps the current {@link ExecutionContext} to the sudo one
+     * @since 2.0
      */
     // tag::refguide[]
-    void sudo(                                              // <.>
-            String username,
-            final Runnable runnable);
+    <T> T call(                                             // <.>
+            @NonNull UnaryOperator<ExecutionContext> sudoMapper,
+            @NonNull Callable<T> supplier);
 
     // end::refguide[]
     /**
      * Executes the supplied block, with the {@link UserService} returning the specified user.
-     *
-     * <p>
-     *    The roles of this user will be the same as the currently logged-in user.
-     * </p>
-     */
-    // tag::refguide[]
-    <T> T sudo(                                             // <.>
-            String username,
-            final Supplier<T> supplier);
-
-    // end::refguide[]
-    /**
-     * Executes the supplied block, with the {@link UserService} returning the specified user with the specified roles.
-     */
-    // tag::refguide[]
-    void sudo(                                              // <.>
-            String username, List<String> roles,
-            final Runnable runnable);
-
-    // end::refguide[]
-    /**
-     * Executes the supplied block, with the {@link UserService} returning the specified user with the specified roles.
+     * @param sudoMapper - maps the current {@link ExecutionContext} to the sudo one
+     * @since 2.0
      */
     // tag::refguide[]
-    <T> T sudo(                                             // <.>
-            String username, List<String> roles,
-            final Supplier<T> supplier);
+    default void run(                                        // <.>
+            final @NonNull UnaryOperator<ExecutionContext> sudoMapper,
+            final @NonNull Runnable runnable) {
+        call(sudoMapper, ()->{runnable.run(); return null;});
+    }
 
     // end::refguide[]
-
-    // tag::refguide-1[]
+    
+    
     /**
      * Allows the {@link SudoService} to notify other services/components that the effective user has been changed.
+     * @since 2.0
      */
-    interface Spi {
+    // tag::refguide-1[]
+    interface Listener {
 
-        // end::refguide-1[]
-        /**
-         * Any implementation of the {@link SudoService} should call this method on all implementations of the
-         * {@link Spi} service whenever {@link SudoService#sudo(String, List, Supplier)} (or its overloads)
-         * is called.
-         *
-         * <p>
-         *     Modelled after Shiro security's <a href="https://shiro.apache.org/static/1.2.6/apidocs/org/apache/shiro/subject/Subject.html#runAs-org.apache.shiro.subject.PrincipalCollection-">runAs</a> support.
-         * </p>
-         */
-        // tag::refguide-1[]
-        void runAs(String username, List<String> roles);    // <.>
+        void beforeCall(@NonNull ExecutionContext before, @NonNull ExecutionContext after);          // <.>
 
-        void releaseRunAs();                                // <.>
+        void afterCall(@NonNull ExecutionContext before, @NonNull ExecutionContext after);          // <.>
     }
     // end::refguide-1[]
 
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/RoleMemento.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/RoleMemento.java
index 1453a09..4558de9 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/RoleMemento.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/RoleMemento.java
@@ -19,14 +19,21 @@
 
 package org.apache.isis.applib.services.user;
 
+import java.io.Serializable;
+
 import org.apache.isis.applib.annotation.MemberOrder;
 
 import lombok.Getter;
+import lombok.Value;
 
+@Value
 // tag::refguide[]
-public final class RoleMemento {
+public final class RoleMemento implements Serializable {
 
     // end::refguide[]
+    
+    private static final long serialVersionUID = -3876856609238378274L;
+    
     /**
      * Creates a new role with the specified name. Description is left blank.
      */
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserMemento.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserMemento.java
index d90ea91..69c5161 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserMemento.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserMemento.java
@@ -19,47 +19,95 @@
 
 package org.apache.isis.applib.services.user;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.io.Serializable;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import javax.annotation.Nullable;
 
 import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.collections._Lists;
 
 import lombok.Getter;
-import lombok.experimental.UtilityClass;
+import lombok.NonNull;
 
 /**
- * Details, obtained from the container, about the user and his roles.
+ * Details about a user and his roles.
  * Read-only.
  */
 // tag::refguide[]
-public final class UserMemento {
-
+public final class UserMemento implements Serializable {
     // end::refguide[]
+    
+    private static final long serialVersionUID = 7190090455587885367L;
+    private static final UserMemento SYSTEM_USER = UserMemento.ofName("__system"); 
+//    private static final UserMemento NO_USER = UserMemento.ofName("__nobody");
+    
+    // -- FACTORIES
+    
+    /**
+     * The framework's internal user with unrestricted privileges.
+     */
+    public static UserMemento system() {
+        return SYSTEM_USER;
+    }
+    
+//    /**
+//     * The framework's internal user with no privileges at all, returned by the
+//     * {@link UserService} if no user is logged in.
+//     */
+//    public static UserMemento nobody() {
+//        return NO_USER;
+//    }
+    
     /**
      * Creates a new user with the specified name and no roles.
      */
-    public UserMemento(final String name) {
-        this(name, new RoleMemento[0]);
+    public static UserMemento ofName(
+            final @NonNull String name) {
+        return new UserMemento(name, Stream.empty());
     }
-
+    
     /**
      * Creates a new user with the specified name and assigned roles.
      */
-    public UserMemento(final String name, final RoleMemento... roles) {
-        this(name, Arrays.asList(roles));
+    public static UserMemento ofNameAndRoles(
+            final @NonNull String name, 
+            final RoleMemento... roles) {
+        return new UserMemento(name, Stream.of(roles));
+    }
+    
+    /**
+     * Creates a new user with the specified name and assigned role names.
+     */
+    public static UserMemento ofNameAndRoleNames(
+            final @NonNull String name, 
+            final String... roleNames) {
+        return new UserMemento(name, Stream.of(roleNames).map(RoleMemento::new));
     }
+    
+    /**
+     * Creates a new user with the specified name and assigned role names.
+     */
+    public static UserMemento ofNameAndRoleNames(
+            final @NonNull String name, 
+            final @NonNull Stream<String> roleNames) {
+        return new UserMemento(name, roleNames.map(RoleMemento::new));
+    }
+    
+    // -- CONSTRUCTOR
 
     /**
      * Creates a new user with the specified name and assigned roles.
      */
-    public UserMemento(final String name, final List<RoleMemento> roles) {
-        if (name == null) {
+    public UserMemento(final String name, final @NonNull Stream<RoleMemento> roles) {
+        if (_Strings.isEmpty(name)) {
             throw new IllegalArgumentException("Name not specified");
         }
         this.name = name;
-        this.roles.addAll(roles);
+        this.roles = roles.collect(_Lists.toUnmodifiable()); 
     }
 
     public String title() {
@@ -79,10 +127,10 @@ public final class UserMemento {
      * The roles associated with this user.
      */
     @MemberOrder(sequence = "1.1")
-    private final List<RoleMemento> roles = new ArrayList<RoleMemento>();
+    private final List<RoleMemento> roles;
     // tag::refguide[]
     public List<RoleMemento> getRoles() {
-        return Collections.unmodifiableList(roles);
+        return roles;
     }
     // end::refguide[]
     /**
@@ -92,35 +140,21 @@ public final class UserMemento {
      *
      * @return true if the names match (is case sensitive).
      */
-    public boolean isCurrentUser(final String userName) {
-        if (userName == null) {
-            throw new IllegalArgumentException("no user name provided");
-        }
+    public boolean isCurrentUser(final @Nullable String userName) {
         return name.equals(userName);
     }
-
-    /**
-     * Determines if the user fulfills the specified role.
-     *
-     * @param role  the role to search for, regular expressions are allowed
-     */
-    public boolean hasRole(final RoleMemento role) {
-        return hasRole(role.getName());
+    
+    public Stream<String> streamRoleNames() {
+        return roles.stream()
+                .map(RoleMemento::getName);
     }
-
-    /**
-     * Determines if the user fulfills the specified role. Roles are compared
-     * lexically by role name.
-     */
-    public boolean hasRole(final String roleName) {
-        for (final RoleMemento role : roles) {
-            if (role.getName().matches(roleName)) {
-                return true;
-            }
-        }
-        return false;
+    
+    public boolean hasRoleName(final @Nullable String roleName) {
+        return streamRoleNames().anyMatch(myRoleName->myRoleName.equals(roleName));
     }
 
+    // -- TO STRING, EQUALS, HASHCODE
+    
     @Override
     public String toString() {
         final StringBuilder buf = new StringBuilder();
@@ -129,18 +163,74 @@ public final class UserMemento {
         }
         return "User [name=" + getName() + ",roles=" + buf.toString() + "]";
     }
-
-    @UtilityClass
-    public static class NameType {
-        @UtilityClass
-        public static class Meta {
-            public static final int MAX_LEN = 50;
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
         }
+        if (obj.getClass() != getClass()) {
+            return false;
+        }
+        return isEqualsTo((UserMemento) obj);
     }
 
+    private boolean isEqualsTo(final UserMemento other) {
+        if(!Objects.equals(this.getName(), other.getName())) {
+            return false;
+        }
+        if(!Objects.equals(this.getRoles(), other.getRoles())) {
+            return false;
+        }
+        return true;
+    }
+    
+    @Override
+    public int hashCode() {
+        return getName().hashCode(); // its good enough to hash on just the user's name
+    }
+    
     // tag::refguide[]
 
     // ...
 
 }
 // end::refguide[]
+
+// -- REMOVED
+
+//XXX implemented as regex match, java-doc is not specific about what these methods actually do; so if in doubt, rather remove     
+///**
+//* Determines if the user fulfills the specified role.
+//*
+//* @param role  the role to search for, regular expressions are allowed
+//*/
+//public boolean hasRole(final RoleMemento role) {
+//  return hasRole(role.getName());
+//}
+//
+///**
+//* Determines if the user fulfills the specified role. Roles are compared
+//* lexically by role name.
+//*/
+//public boolean hasRole(final String roleName) {
+//  for (final RoleMemento role : roles) {
+//      if (role.getName().matches(roleName)) {
+//          return true;
+//      }
+//  }
+//  return false;
+//}
+
+//XXX not used    
+//@UtilityClass
+//public static class NameType {
+//  @UtilityClass
+//  public static class Meta {
+//      public static final int MAX_LEN = 50;
+//  }
+//}
+
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserService.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserService.java
index e12ff02..826fc7d 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserService.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/user/UserService.java
@@ -16,18 +16,56 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.apache.isis.applib.services.user;
 
+import java.util.Optional;
+
+import org.apache.isis.applib.services.iactn.ExecutionContext;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+
 // tag::refguide[]
 public interface UserService {
 
+    // -- INTERFACE
+    
+    // end::refguide[]
+    /**
+     * Optionally gets the details about the current user, 
+     * based on whether an {@link ExecutionContext} can be found with the current thread's context.
+     */
+    // tag::refguide[]
+    Optional<UserMemento> getUser();    // <.>
+
+    // end::refguide[]
+    
+    // -- UTILITIES
+    
+    /**
+     * Gets the details about the current user.
+     * @throws IllegalStateException if no {@link ExecutionContext} can be found with the current thread's context.
+     */
+    // tag::refguide[]
+    default UserMemento getUserElseFail() {              // <.>
+        // end::refguide[]
+        return getUser()
+                .orElseThrow(()->_Exceptions.illegalState("Current thread has no ExecutionContext."));
+    }
+    
     // end::refguide[]
     /**
-     * Get the details about the current user.
+     * Optionally gets the the current user's name, 
+     * based on whether an {@link ExecutionContext} can be found with the current thread's context.
      */
     // tag::refguide[]
-    UserMemento getUser();      // <.>
+    default Optional<String> getUserName() {    // <.>
+        return getUser()
+                .map(UserMemento::getName);
+    }
+    
+    default String getUserNameElseNobody() {    // <.>
+        return getUserName()
+                .orElse("Nobody");
+    }
 
 }
 // end::refguide[]
diff --git a/api/applib/src/main/adoc/modules/applib-svc/examples/services/wrapper/control/AsyncControl.java b/api/applib/src/main/adoc/modules/applib-svc/examples/services/wrapper/control/AsyncControl.java
index 3c91242..c95027e 100644
--- a/api/applib/src/main/adoc/modules/applib-svc/examples/services/wrapper/control/AsyncControl.java
+++ b/api/applib/src/main/adoc/modules/applib-svc/examples/services/wrapper/control/AsyncControl.java
@@ -18,13 +18,15 @@
  */
 package org.apache.isis.applib.services.wrapper.control;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.Future;
 
+import org.apache.isis.applib.clock.VirtualClock;
+import org.apache.isis.applib.services.user.UserMemento;
+
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.Setter;
@@ -69,14 +71,14 @@ public class AsyncControl<R> extends ControlAbstract<AsyncControl<R>> {
 
     // end::refguide[]
     /**
-     * Defaults to user initiating the action, if not overridden
+     * Defaults to the system clock, if not overridden
      */
     // tag::refguide[]
     @Getter
-    private String user;                                                // <.>
-    public AsyncControl<R> withUser(final String user) {
+    private VirtualClock clock;                                         // <.>
+    public AsyncControl<R> withClock(final @NonNull VirtualClock clock) {
         // end::refguide[]
-        this.user = user;
+        this.clock = clock;
         return this;
         // tag::refguide[]
         // ...
@@ -84,21 +86,47 @@ public class AsyncControl<R> extends ControlAbstract<AsyncControl<R>> {
 
     // end::refguide[]
     /**
-     * Defaults to roles of user initiating the action, if not overridden
+     * Defaults to the system locale, if not overridden
      */
     // tag::refguide[]
     @Getter
-    private List<String> roles;                                         // <.>
-    public AsyncControl<R> withRoles(final List<String> roles) {
+    private Locale locale;                                         // <.>
+    public AsyncControl<R> withLocale(final @NonNull Locale locale) {
         // end::refguide[]
-        this.roles = Collections.unmodifiableList(roles);
+        this.locale = locale;
         return this;
         // tag::refguide[]
         // ...
     }
-    public AsyncControl<R> withRoles(String... roles) {
+
+    // end::refguide[]
+    /**
+     * Defaults to the system time zone, if not overridden
+     */
+    // tag::refguide[]
+    @Getter
+    private TimeZone timeZone;                                         // <.>
+    public AsyncControl<R> withTimeZone(final @NonNull TimeZone timeZone) {
         // end::refguide[]
-        return withRoles(Arrays.asList(roles));
+        this.timeZone = timeZone;
+        return this;
+        // tag::refguide[]
+        // ...
+    }
+
+    // end::refguide[]
+
+
+    /**
+     * Defaults to user initiating the action, if not overridden
+     */
+    // tag::refguide[]
+    @Getter
+    private UserMemento user;                                           // <.>
+    public AsyncControl<R> withUser(final @NonNull UserMemento user) {
+        // end::refguide[]
+        this.user = user;
+        return this;
         // tag::refguide[]
         // ...
     }
diff --git a/core/config/src/main/adoc/modules/config/pages/sections/resteasy.adoc b/core/config/src/main/adoc/modules/config/pages/sections/resteasy.adoc
index 89b3857..984e90f 100644
--- a/core/config/src/main/adoc/modules/config/pages/sections/resteasy.adoc
+++ b/core/config/src/main/adoc/modules/config/pages/sections/resteasy.adoc
@@ -25,7 +25,7 @@ resteasy.authentication. +
 strategy-class-name
 
 | 
-| Defaults to ``AuthenticationSessionStrategyBasicAuth``.
+| Defaults to ``AuthenticationStrategyBasicAuth``.
 
 
 |
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
index a0b5713..f33dd55 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/session/InteractionFactoryDefault.java
@@ -152,10 +152,10 @@ implements InteractionFactory, InteractionTracker {
     }
     
     @Override
-    public InteractionLayer openInteraction(final @NonNull Authentication authSessionToUse) {
+    public InteractionLayer openInteraction(final @NonNull Authentication authToUse) {
 
         val interactionSession = getOrCreateInteractionSession();
-        val newInteractionClosure = new InteractionLayer(interactionSession, authSessionToUse);
+        val newInteractionClosure = new InteractionLayer(interactionSession, authToUse);
         
         interactionLayerStack.get().push(newInteractionClosure);
 
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
index 047f90e..c200024 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
@@ -327,7 +327,7 @@ public class WrapperFactoryDefault implements WrapperFactory {
             final AsyncControl<R> asyncControl) {
 
         val interactionLayer = currentInteractionLayer();
-        val asyncAuth = authSessionFrom(asyncControl, interactionLayer.getAuthentication());
+        val asyncAuth = authFrom(asyncControl, interactionLayer.getAuthentication());
         val command = interactionContextProvider.get().getInteractionElseFail().getCommand();
         val commandUniqueId = command.getUniqueId();
 
@@ -425,9 +425,9 @@ public class WrapperFactoryDefault implements WrapperFactory {
         return MemberAndTarget.foundAction(targetActionIfAny.get(), currentObjectManager().adapt(mixedIn), method);
     }
 
-    private static <R> Authentication authSessionFrom(AsyncControl<R> asyncControl, Authentication authSession) {
+    private static <R> Authentication authFrom(AsyncControl<R> asyncControl, Authentication auth) {
     
-        val executionContext = authSession.getExecutionContext();
+        val executionContext = auth.getExecutionContext();
         
         val newExecutionContext = ExecutionContext.builder()
         .clock(Optional.ofNullable(asyncControl.getClock())
@@ -440,7 +440,7 @@ public class WrapperFactoryDefault implements WrapperFactory {
                 .orElseGet(executionContext::getUser))
         .build();
         
-        return authSession.withExecutionContext(newExecutionContext);
+        return auth.withExecutionContext(newExecutionContext);
         
     }
 
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 86f9e19..42a7869 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
@@ -94,10 +94,10 @@ public class AuthenticationManager {
         }
         
         for (final Authenticator authenticator : compatibleAuthenticators) {
-            val authSession = authenticator.authenticate(request, getUnusedRandomCode());
-            if (authSession != null) {
-                userByValidationCode.put(authSession.getValidationCode(), authSession.getUserName());
-                return authSession;
+            val authentication = authenticator.authenticate(request, getUnusedRandomCode());
+            if (authentication != null) {
+                userByValidationCode.put(authentication.getValidationCode(), authentication.getUserName());
+                return authentication;
             }
         }
         
diff --git a/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/job/ReplicateAndReplayJob.java b/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/job/ReplicateAndReplayJob.java
index 55b0c3b..8996aa7 100644
--- a/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/job/ReplicateAndReplayJob.java
+++ b/extensions/core/command-replay/secondary/src/main/java/org/apache/isis/extensions/commandreplay/secondary/job/ReplicateAndReplayJob.java
@@ -44,7 +44,7 @@ public class ReplicateAndReplayJob implements Job {
 
     @Inject SecondaryConfig secondaryConfig;
 
-    Authentication authSession;
+    Authentication authentication;
 
     public void execute(final JobExecutionContext quartzContext) {
 
@@ -56,7 +56,7 @@ public class ReplicateAndReplayJob implements Job {
                     secondaryConfig.getPrimaryUser(), 
                     secondaryConfig.getQuartzRoles().stream());
             
-            authSession = SimpleAuthentication.validOf(user);
+            authentication = SimpleAuthentication.validOf(user);
             exec(quartzContext);
         }
     }
@@ -72,7 +72,7 @@ public class ReplicateAndReplayJob implements Job {
             case TICKING_CLOCK_STATUS_UNKNOWN:
             case TICKING_CLOCK_NOT_YET_INITIALIZED:
                 ssh.setSecondaryStatus(
-                        isTickingClockInitialized(authSession)
+                        isTickingClockInitialized(authentication)
                             ? SecondaryStatus.OK
                             : SecondaryStatus.TICKING_CLOCK_NOT_YET_INITIALIZED);
                 if(ssh.getSecondaryStatus() == SecondaryStatus.OK) {
@@ -84,7 +84,7 @@ public class ReplicateAndReplayJob implements Job {
 
             case OK:
                 val newStatus =
-                        isisInteractionFactory.callAuthenticated(authSession, new ReplicateAndRunCommands());
+                        isisInteractionFactory.callAuthenticated(authentication, new ReplicateAndRunCommands());
 
                 if(newStatus != null) {
                     ssh.setSecondaryStatus(newStatus);
@@ -101,8 +101,8 @@ public class ReplicateAndReplayJob implements Job {
         }
     }
 
-    private boolean isTickingClockInitialized(final Authentication authSession) {
-        return isisInteractionFactory.callAuthenticated(authSession, new IsTickingClockInitialized());
+    private boolean isTickingClockInitialized(final Authentication authentication) {
+        return isisInteractionFactory.callAuthenticated(authentication, new IsTickingClockInitialized());
     }
 
 }
diff --git a/extensions/core/quartz/adoc/modules/quartz/examples/DemoJob.java b/extensions/core/quartz/adoc/modules/quartz/examples/DemoJob.java
index 95232f4..d82d9ca 100644
--- a/extensions/core/quartz/adoc/modules/quartz/examples/DemoJob.java
+++ b/extensions/core/quartz/adoc/modules/quartz/examples/DemoJob.java
@@ -41,7 +41,7 @@ public class DemoJob implements Job {
 
     public void execute(final JobExecutionContext context) {
 
-        final Authentication authSession = newAuthSession(context);
+        final Authentication auth = newAuthSession(context);
         new DemoIsisInteractionTemplate().execute(authSession, null);
 
     }
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/AuthSessionStoreUtil.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/AuthSessionStoreUtil.java
index 80a58b1..6f8ab85 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/AuthSessionStoreUtil.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/AuthSessionStoreUtil.java
@@ -42,8 +42,8 @@ public class AuthSessionStoreUtil {
 
     public static void put(
             @NonNull final HttpSession httpSession, 
-            @Nullable final Authentication authSession) {
-        httpSession.setAttribute(Authentication.class.getName(), authSession);
+            @Nullable final Authentication auth) {
+        httpSession.setAttribute(Authentication.class.getName(), auth);
     }
     
     public static Optional<Authentication> get(
@@ -55,11 +55,11 @@ public class AuthSessionStoreUtil {
     
     /** when within a VaadinSession */
     public static void put(
-            @Nullable final Authentication authSession) {
+            @Nullable final Authentication auth) {
         Optional.ofNullable(VaadinSession.getCurrent())
         .map(VaadinSession::getSession)
         .ifPresent(sessionVaa->{
-            sessionVaa.setAttribute(Authentication.class.getName(), authSession);    
+            sessionVaa.setAttribute(Authentication.class.getName(), auth);    
         });
     }
     
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/LogoutHandlerVaa.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/LogoutHandlerVaa.java
index 1a0e252..236839d 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/LogoutHandlerVaa.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/LogoutHandlerVaa.java
@@ -46,10 +46,10 @@ public class LogoutHandlerVaa implements LogoutHandler {
         }
         
         AuthSessionStoreUtil.get()
-        .ifPresent(authSession->{
-            log.info("logging out {}", authSession.getUserName());
+        .ifPresent(auth->{
+            log.info("logging out {}", auth.getUserName());
             // logout AuthenticationManager
-            metaModelContext.getAuthenticationManager().closeSession(authSession);
+            metaModelContext.getAuthenticationManager().closeSession(auth);
             AuthSessionStoreUtil.clear();
         });
         
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/VaadinAuthenticationHandler.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/VaadinAuthenticationHandler.java
index 1e6d57d..92b6fe5 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/VaadinAuthenticationHandler.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/auth/VaadinAuthenticationHandler.java
@@ -68,12 +68,12 @@ public class VaadinAuthenticationHandler implements VaadinServiceInitListener {
      * @return whether login was successful
      */
     public boolean loginToSession(AuthenticationRequest authenticationRequest) {
-        val authSession = metaModelContext.getAuthenticationManager()
+        val authentication = metaModelContext.getAuthenticationManager()
                 .authenticate(authenticationRequest);
         
-        if(authSession!=null) {
-            log.debug("logging in {}", authSession.getUserName());
-            AuthSessionStoreUtil.put(authSession);
+        if(authentication!=null) {
+            log.debug("logging in {}", authentication.getUserName());
+            AuthSessionStoreUtil.put(authentication);
             return true;
         }
         return false;
@@ -89,7 +89,7 @@ public class VaadinAuthenticationHandler implements VaadinServiceInitListener {
      */
     public <R> R callAuthenticated(Callable<R> callable) {
         return AuthSessionStoreUtil.get()
-                .map(authSession->isisInteractionFactory.callAuthenticated(authSession, callable))
+                .map(authentication->isisInteractionFactory.callAuthenticated(authentication, callable))
                 .orElse(null); // TODO redirect to login
     }
     
@@ -109,9 +109,9 @@ public class VaadinAuthenticationHandler implements VaadinServiceInitListener {
         val targetView = event.getNavigationTarget();
         log.debug("detected a routing event to {}", targetView);
         
-        val authSession = AuthSessionStoreUtil.get().orElse(null);
-        if(authSession!=null) {
-            isisInteractionFactory.openInteraction(authSession);
+        val authentication = AuthSessionStoreUtil.get().orElse(null);
+        if(authentication!=null) {
+            isisInteractionFactory.openInteraction(authentication);
             return; // access granted
         }
         // otherwise redirect to login page
diff --git a/incubator/viewers/vaadin/viewer/src/main/java/org/apache/isis/incubator/viewer/vaadin/viewer/IsisServletForVaadin.java b/incubator/viewers/vaadin/viewer/src/main/java/org/apache/isis/incubator/viewer/vaadin/viewer/IsisServletForVaadin.java
index f4469c3..8f45614 100644
--- a/incubator/viewers/vaadin/viewer/src/main/java/org/apache/isis/incubator/viewer/vaadin/viewer/IsisServletForVaadin.java
+++ b/incubator/viewers/vaadin/viewer/src/main/java/org/apache/isis/incubator/viewer/vaadin/viewer/IsisServletForVaadin.java
@@ -62,13 +62,13 @@ extends SpringServlet {
     protected void service(HttpServletRequest request,
             HttpServletResponse response) throws ServletException, IOException {
         
-        val authSession = AuthSessionStoreUtil.get(request.getSession(true))
+        val authentication = AuthSessionStoreUtil.get(request.getSession(true))
                 .orElse(null);
         
-        log.debug("new request incoming (authentication={})", authSession);
+        log.debug("new request incoming (authentication={})", authentication);
         
-        if(authSession!=null) {
-            isisInteractionFactory.runAuthenticated(authSession, ()->{
+        if(authentication!=null) {
+            isisInteractionFactory.runAuthenticated(authentication, ()->{
                 super.service(request, response);                
             });
         } else {
@@ -77,11 +77,11 @@ extends SpringServlet {
             super.service(request, response);    
         }
         
-        log.debug("request was successfully serviced (authentication={})", authSession);
+        log.debug("request was successfully serviced (authentication={})", authentication);
         
         if(isisInteractionFactory.isInInteractionSession()) {
             isisInteractionFactory.closeSessionStack();
-            log.warn("after servicing current request some interactions have been closed forcefully (authentication={})", authSession);
+            log.warn("after servicing current request some interactions have been closed forcefully (authentication={})", authentication);
         }
         
     }
diff --git a/viewers/restfulobjects/adoc/modules/ROOT/partials/security/user-registration.adoc b/viewers/restfulobjects/adoc/modules/ROOT/partials/security/user-registration.adoc
index 351c097..e4152db 100644
--- a/viewers/restfulobjects/adoc/modules/ROOT/partials/security/user-registration.adoc
+++ b/viewers/restfulobjects/adoc/modules/ROOT/partials/security/user-registration.adoc
@@ -32,7 +32,7 @@ Here `AuthenticationSession` is Apache Isis' internal API that represents a sign
 
 The framework provides a number of simple strategies:
 
-* `AuthenticationSessionStrategyBasicAuth` implements the HTTP basic auth protocol (the pop-up dialog box shown by the web browser)
+* `AuthenticationStrategyBasicAuth` implements the HTTP basic auth protocol (the pop-up dialog box shown by the web browser)
 * `AuthenticationSessionStrategyHeader` that simply reads the user identity from an HTTP header
 * `AuthenticationSessionStrategyTrusted` that always logs in with a special "exploration" user
 
@@ -50,7 +50,7 @@ The strategy is configured in `web.xml`; for example:
     <init-param>
         <param-name>authenticationSessionStrategy</param-name>
         <param-value>                                           <!--1-->
-    org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationSessionStrategyBasicAuth
+    org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationStrategyBasicAuth
         </param-value>
     </init-param>
     <init-param>
@@ -145,7 +145,7 @@ Next, we need to ensure that a client can hit your new resource *with* the Apach
 
 * create a subclass of the `AuthenticationSessionStrategy` that automatically returns a dummy session if the resource being accessed is "/restful/signup", say.  +
 +
-You could do this by subclassing `AuthenticationSessionStrategyBasicAuth`, but then using code from `AuthenticationSessionStrategyBasicAuth` to return an "exploration" (or better, "signup") session if accessing the "/restful/signup" resource.
+You could do this by subclassing `AuthenticationStrategyBasicAuth`, but then using code from `AuthenticationStrategyBasicAuth` to return an "exploration" (or better, "signup") session if accessing the "/restful/signup" resource.
 
 * in the `SignUpResource` resource, you can then do a lookup of the `UserRegistrationService` in order to allow the user to be created: +
 +
diff --git a/viewers/restfulobjects/adoc/modules/ROOT/partials/security/web-xml.adoc b/viewers/restfulobjects/adoc/modules/ROOT/partials/security/web-xml.adoc
index 0c6ba74..b215d7e 100644
--- a/viewers/restfulobjects/adoc/modules/ROOT/partials/security/web-xml.adoc
+++ b/viewers/restfulobjects/adoc/modules/ROOT/partials/security/web-xml.adoc
@@ -32,7 +32,7 @@ Here `AuthenticationSession` is Apache Isis' internal API that represents a sign
 
 The framework provides a number of simple strategies:
 
-* `AuthenticationSessionStrategyBasicAuth` implements the HTTP basic auth protocol (the pop-up dialog box shown by the web browser)
+* `AuthenticationStrategyBasicAuth` implements the HTTP basic auth protocol (the pop-up dialog box shown by the web browser)
 * `AuthenticationSessionStrategyHeader` that simply reads the user identity from an HTTP header
 * `AuthenticationSessionStrategyTrusted` that always logs in with a special "exploration" user
 
@@ -50,7 +50,7 @@ The strategy is configured in `web.xml`; for example:
     <init-param>
         <param-name>authenticationSessionStrategy</param-name>
         <param-value>                                           <!--1-->
-    org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationSessionStrategyBasicAuth
+    org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationStrategyBasicAuth
         </param-value>
     </init-param>
     <init-param>
diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/IsisRestfulObjectsInteractionFilter.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/IsisRestfulObjectsInteractionFilter.java
index 29bbcd6..8f0be7e 100644
--- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/IsisRestfulObjectsInteractionFilter.java
+++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/IsisRestfulObjectsInteractionFilter.java
@@ -237,7 +237,7 @@ public class IsisRestfulObjectsInteractionFilter implements Filter {
     }
 
 
-    private AuthenticationStrategy authSessionStrategy;
+    private AuthenticationStrategy authStrategy;
     private List<String> restrictedPaths;
     private WhenNoSession whenNotAuthenticated;
     private String redirectToOnException;
@@ -252,7 +252,7 @@ public class IsisRestfulObjectsInteractionFilter implements Filter {
 
     @Override
     public void init(final FilterConfig config) throws ServletException {
-        authSessionStrategy = lookup(config.getInitParameter(AUTHENTICATION_SESSION_STRATEGY_KEY));
+        authStrategy = lookup(config.getInitParameter(AUTHENTICATION_SESSION_STRATEGY_KEY));
         lookupWhenNoSession(config);
         lookupPassThru(config);
         lookupRedirectToOnException(config);
@@ -356,7 +356,7 @@ public class IsisRestfulObjectsInteractionFilter implements Filter {
             if (queryString != null && queryString
                     .contains(ISIS_SESSION_FILTER_QUERY_STRING_FORCE_LOGOUT)) {
 
-                authSessionStrategy.invalidate(httpServletRequest, httpServletResponse);
+                authStrategy.invalidate(httpServletRequest, httpServletResponse);
                 return;
             }
 
@@ -373,10 +373,10 @@ public class IsisRestfulObjectsInteractionFilter implements Filter {
             
             // authenticate
             val authentication =
-                    authSessionStrategy.lookupValid(httpServletRequest, httpServletResponse);
+                    authStrategy.lookupValid(httpServletRequest, httpServletResponse);
             if (authentication != null) {
                 
-                authSessionStrategy.bind(httpServletRequest, httpServletResponse, authentication);
+                authStrategy.bind(httpServletRequest, httpServletResponse, authentication);
                 
                 isisInteractionFactory.runAuthenticated(
                         authentication,
diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.java
index 62a4868..172280d 100644
--- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.java
+++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategy.java
@@ -43,12 +43,12 @@ public interface AuthenticationStrategy {
      * Binds the request to a still-valid {@link Authentication} if applicable
      * @param httpServletRequest
      * @param httpServletResponse
-     * @param authSession
+     * @param auth
      */
     void bind(
             HttpServletRequest httpServletRequest, 
             HttpServletResponse httpServletResponse, 
-            Authentication authSession);
+            Authentication auth);
 
     void invalidate(
             HttpServletRequest httpServletRequest, 
diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.java
index ef2b871..3e5ad66 100644
--- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.java
+++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyBasicAuth.java
@@ -81,7 +81,7 @@ public class AuthenticationStrategyBasicAuth extends AuthenticationStrategyAbstr
     public void bind(
             HttpServletRequest httpServletRequest, 
             HttpServletResponse httpServletResponse,
-            Authentication authSession) {
+            Authentication auth) {
         // TODO Auto-generated method stub
         
     }
diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.java
index 99f8cfe..e07c72c 100644
--- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.java
+++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/webmodule/auth/AuthenticationStrategyDefault.java
@@ -53,12 +53,12 @@ public class AuthenticationStrategyDefault extends AuthenticationStrategyAbstrac
         val httpSession = getHttpSession(httpServletRequest);
 
         // use previously authenticated session if available
-        val authSession = (Authentication) 
+        val authentication = (Authentication) 
                 httpSession.getAttribute(HTTP_SESSION_AUTHENTICATION_SESSION_KEY);
-        if (authSession != null) {
-            val sessionValid = authenticationManager.isSessionValid(authSession);
+        if (authentication != null) {
+            val sessionValid = authenticationManager.isSessionValid(authentication);
             if (sessionValid) {
-                return authSession;
+                return authentication;
             }
         }
 
@@ -69,12 +69,12 @@ public class AuthenticationStrategyDefault extends AuthenticationStrategyAbstrac
     public void bind(
             final HttpServletRequest httpServletRequest,
             final HttpServletResponse httpServletResponse,
-            final Authentication authSession) {
+            final Authentication authentication) {
         
         val httpSession = getHttpSession(httpServletRequest);
-        if(authSession != null) {
+        if(authentication != null) {
             httpSession.setAttribute(
-                    HTTP_SESSION_AUTHENTICATION_SESSION_KEY, authSession);
+                    HTTP_SESSION_AUTHENTICATION_SESSION_KEY, authentication);
         } else {
             httpSession.removeAttribute(HTTP_SESSION_AUTHENTICATION_SESSION_KEY);
         }