tl;dr skip to the last paragraph
After discussion on IRC and more thinking, we probably should decide between using
Update for all objects edits, and using specific activities for specific changes.
Pros of using
- No need to add custom activities for the various changes, just use
Update and the recipient figures out what changed
- Perhaps less dev work, just implement a generic Update handler, it doesn’t even have to understand the
type of the object being updated (but this is questionable because need to implement diffing for viewing and for determining exact changes when it matters for authorizing the change… see below)
Pros of using specific activities:
- When observing an activity, it’s trivial to tell exactly what it changed; with Update it would be impossible to tell what the activity did
- When observing the
history of an object, telling what each
Update did may be possible by diffing the
Updates, but that works only if there’s no possibility for other activities to edit fields, otherwise the diffing would be confused. For example if some activity has a side effect that edits some field, the software observing the
history would have to understand this activity and be able to simulate the side effect. Is there a good reason to be confident there’s a fixed set of activities that edit fields, and the edits can always be simulated?
- Many activities make edits to objects (e.g.
Follow edits a followers collection), and
Update is only one of them. How do we decide what uses
Update and what doesn’t? Suppose we decide that
Update is for changes that don’t have any special side effects. Now merging an MR or applying a patch can’t use
Update, because there’s a side effect. So whenever editing fields is a side effect of an activity that does something else, like applying a patch to a repo, any software viewing a
history collection where it appears would have to understand it and be able to simulate the fields edits, otherwise the diffing of activities will get confused.
Clarification: We don’t need a custom activity for every single editable field, it just needs to be expressive enough for the kind of viewing forges offer, and the different distinguishable actions that have their own authorization rules. A simple rule: If an object history page displays some event in specific words (and not “user X updated object Y”) or there’s a dedicated button in UI to trigger this event, then we probably want to give is a dedicated activity type. There are just few of those per object type, so we it would be a small manageable number of custom activities to add. For example, a ticket’s data that isn’t in sub-objects is mostly just its textual content, perhaps who’s assigned to it, whether it’s resolved, the due date, maybe the tags if they aren’t in their own Collection… there are just few kinds of edits on these fields.
Update means we don’t add custom vocabulary for kinds of changes, but I’m worried we’d end up making ourselves really struggle with that silly diffing of activities to determine what they did. The exact change is already known in advance, there’s specific intention to edit specific field(s), but instead of preserving that info, we’d be working with full objects and doing complicated processing to figure out that initial intention. There are fields related to each other, e.g.
resolved all refer to the same event, of a ticket being resolved, so the software would be looking at them carefully, trying to figure out which of those 3 got changed and why and what it means and does
resolvedBy match the
actor of the
Update, otherwise that’s quite confusing, etc. etc.
Activity diffing may be required for determining authorization e.g. maybe some user is allowed to close/reopen a ticket, but not allowed to change its due date.
If we go for specific activities, it does mean we add custom activity types, but the implementation of those activities is extremely simple, no diffing is required, generating UI for viewing them would be trivial too. Forges already have pages and endpoints for specific actions like a “Close this ticket” button on a ticket page, right? They already handle changes in this way, and not via generic updates. So they’d simply have federation-supporting variants of those handlers, the “close this ticket” handler would support both a button click from a local user, and a remote e.g.
Resolve activity coming from a remote user.
Can I please hear some good arguments in favor of using just
Update for all the object changes? otherwise, it seems so much simpler to add specific activities that do specific clear obvious edits, making authorization and display trivial to implement. We could still use
Update, keeping it for the case where the display of “user X updated object Y” is enough, and perhaps specifying specific fields intended to be changed in that way (e.g. a ticket’s title and description). Then
Update becomes trivial to handle too.
Note that most AP implementations use just S2S so they probably don’t care about viewing since they have their own custom C2S API for that, but C2S/viewing is in the spec, and they’re picking activities just for their own use while we’re writing a spec so we’re thinking bigger than covering the needs of one specific implementation.