I should be able to view Recent Changes in this Space

(User Story, Closed -> Fixed, Priority: Critical, Test Status: No automated tests yet , Reported By Bad Link: Thing 3y284oe not found, )
Summary: This is the underlying Epic behind a lot of Eric's recent requests. It is the holding pen for designing the sucker; bits will get broken out into their own stories.
Depends Upon:
Not all of the below is likely to be implemented at once, or in the order shown below; this should be viewed as a medium-term plan for the eventual, full-fledged feature.

Minor Changes

We will add a new concept of a "Minor Change" -- see I should be able to edit and save changes coherently and I should be able to show a "Minor Changes" button for the stories to make this work.

Accessing History

The high concept here is that we are going to provide userspace access to the History. Currently, it can only be accessed by the Owner, but it's getting to be time to widen that.
So we will add a _getChanges(since, until, changesTo, includeMinor, viewAsPublic, coalesce) function. This produces a list of Change records, in order; each record includes the timestamp, the state of the Thing before the change (if it existed and this user was allowed to see it), and a set of changed Property values. (There will also need to be some representation for Deleted.) This function works Space-wide.
All parameters are optional, and they won't all be implemented at once. They are:
  • since -- the starting date we are interested in. (Default: origin of this Space.)
  • until -- the end date we are interested in. (Default: now.)
  • changesTo -- a list of Things; if Instances, only show changes to those Instances; if Models, only show changes to those Models and their Instances. (Default: everything this User can see.)
  • includeMinor -- include Minor Changes. (Default: false)
  • viewAsPublic -- iff true, always shows the view the way the Public security principal does, so the owner can see the Public view. (Default: false)
  • coalesce -- iff true, only include at most one change record for any given Thing, which will incorporate all of the changes that actually happened. (Default: not sure -- might be true.)

Rendering

Rendering of the changes is mainly a userspace operation, since I suspect Eric is going to want to be able to tune it to his preferences.
The change record might include text diffs automatically. While this could be implemented in userspace, it's likely always desireable, so we may want to just build it in. See I should be able to see Text diffs showing the changes between two times for a given Thing / Property for more thoughts about diffs.
All that said, Change Records should have a sensible default rendering that looks decent, so that you can just run _getChanges() and show the output.
Note that this might become the underlying basis of a new version of History that is safe to expose to users.

Security

Initially, the system will automatically filter the change list for changes to things that this User is allowed to see at the time of the event.
Iff the actual Modify event was to permissions, such that the user could not see the Thing before and now can, it comes out as a Create. (Similarly, if permissions changed to hide it, that is shown as a Delete.) This is necessary so that we don't leak information about Things this User isn't allowed to see.
In the long run, this feature is likely to want to interact with Bless, so that the owner can include changes that might not otherwise be visible. But that's not an obviously necessary use case, so we're not going to worry about it for now.
The viewAsPublic parameter is a bit of a hack -- in principle, this should really allow you to specify any Security Principal. But in practice, that is dangerous from security POV until and unless we have a clear concept of whether a given Security Principal has more or less access than another, and who wrote this expression: you should only be allowed to specify a target that has strictly less rights than yourself. This probably can't be done safely until we have Bless, and can restrict this parameter based on it.

Building it in

Once all of this is working decently well, we might want to make it automatic as a built-in. This would be a standard page on all Spaces, showing the output of _getChanges. This would need some mechanism to disable it, as well as to specify the desired parameters, but it's likely generally useful enough to make it standard.

Optimization

Under the hood, _getChanges() delegates to the SpaceHistory. The problem with that is that the History takes a very long time to build.
In the medium term, therefore, we should enhance SpaceHistory to only read enough of the History to do this -- which means we need to be able to start from a particular Snapshot. Which Persistence Query can't do yet.
Patrik has suggested a hack to get this started: we could boot up a specialized Persistent Actor (not a Query) with this Persistence ID, absolutely no persist commands, and a Recovery / SnapshotSelectionCriteria tuned to the beginning of the desired range; we would fetch the Snapshot and subsequent events through that, and build up a partial History from it.
In the longer term, Patrik is encouraging me to form akka-persistence-cassandra and enhance it with the functions I need:
  • Get a stream of the SnapshotMetadata for this persistenceId (as illustrated in CassandraSnapshotStore.metadata()).
  • Fetch a Snapshot based on a particular SnapshotMetadata.
The needed functionality is mostly already in CassandraSnapshotStore (in akka-persistence-cassandra); the only real issue is how to expose it to the API. Come up with a plan, and talk with the Akka team about it. Patrik has indicated that he is open to a PR for this, and might add it to the standard Persistence Query API if it makes sense.