Skip to content
Mathieu Leplatre edited this page Jul 4, 2016 · 7 revisions

History of changes

For some applications we want to keep an history of changes on the data of the application.

This is a common usecase and for instance the Django Admin have got a LogEntry for the very similar use-case.

What do we want to log?

  • The history should track changes of collection records
  • The history should track changes of collection metadata (track changes of jsonschema or signature status)
  • The history should track changes of bucket metadata (track changes of administration permissions)
  • The history should track changes of group metadata (track changes of editors and groups permissions changes)

How do we want to log?

History collection endpoint

After investigating multiple alternatives it seems that having a history collection for the bucket (name configurable in the configuration as well as resources patterns that have an history) would be a good solution:

/v1/buckets/staging/collections/history/records

We need to make sure that this history collection won't be taken into account by other plugins such as the signer, changes, or the history itself (keeping track of the history would have interesting consequences)

Record properties

Each history record contains:

  • who: The prefixed_userID of the person doing the change
  • last_modified: The date of the modification
  • action: create/update or delete
  • resource: Information about the resource.
    • uri: The resource URI
    • resource_name: The resource_name (bucket/collection/group/record)
    • bucket_id: The bucket ID
    • collection_id: The collection ID
    • id: The resource ID
  • data: The record data
  • permissions: The record permission

Record permissions

The history record is read-only and new record in the history collection can only be added by the kinto-history plugin.

Read permissions of record are calculated by building a set containing all principals of the write and read permission of the resource as well as the write and read permission of the collection (if it is a record).

Example of a history record

{
  "data": {
    "who": "fxa:123456789012",
    "when": "2016-07-04T11:34:15.513795",
    "last_modified": 1467278674621,
    "action": "create",
    "resource": {
      "uri": "/buckets/2f9b1aaa-552d-48e8-1b78-371dd08688b3/collections/test",
      "resource_name": "collection",
      "bucket_id": "2f9b1aaa-552d-48e8-1b78-371dd08688b3",
      "collection_id": "test",
      "id": "test"
    },
    "data": {
      "id": "test",
      "last_modified": 1467278674512
    },
    "permissions": {
      "write": ["fxa:123456789012"]
    }
  },
  "permissions": {
    "read": ["fxa:123456789012"]
  }
}

Batch requests

The ResourceChanged impacted records event data of a batch request is split in order to build an history record per changes.

Capability

A capability called «history» reveals presence of plugin.

History pruning

It might be interesting to think about for how long we want to keep the history for.

Depending on the use case you might want to use one of the following pruning strategy:

  • The 5 last changes of a given record (when record are updated not so often)
  • The last 5 days of changes (when records are updated multiple times a week)
  • Keep the last 10000 changes in total for a bucket (for application that creates a lot of collections)
  • Add a way to let the administrator manually prune some records

We will wait for use-cases before implementing them; as such, all the strategies described above might not be implemented as part of the first version.

Nice to have: RSS content-type

The history resource accepts a RSS application/rss+xml content-type which allow to subscribe to a stream of modification for the bucket history. It accepts the same query string filters and respects the permissions policies.

It is a nice-to-have and it might not be implemented as part as the the first version.