This document is a work in progress and will evolve as we clean up the API.
The main purpose of this document is to establish the API for version 1.0 of the library.
The structure of the models will be different than what it is today.
- The
activitypubmodule will be renamed tovocaband contain the vanilla types described in the Activity vocabulary specification. - The
processingmodule will become the newactivitypubmodule, and it will contain the state machine for processing client to server and server to server activities.- It will include subpackages for convenience functionality to interop with the wider Go ecosystem: HTTP handlers
- The
authorizationmodule moves as a subpackage here.
- The
clientmodule stays as is.
The vocabulary
Generating code should start from a Go struct with annotations.
The steps should be something like this:
Structure
We need to validate the struct’s compatibility with the Vanilla AP objects:
- the properties must match the position and type of one of the
Object,Actor,IntransitiveActivity,Activity,Link, etc. - the struct must validate against the JSON-LD contexts that the developer chooses for them.
Helper functions
Generate helper functions:
- Initializer function:
New<Type> - Generate functions:
On<StructName>, andTo<StructName> - Generate function type
With<Type>Fn - Generate
MarshalJSON/UnmarshalJSON,GobEncode/GobDecode - Add type switch cases to the
IsObject,IsActor,IsActivity,IsIntransitiveActivity,IsLink - Add type switch cases to the
ToObject,ToActor,ToActivity,ToIntransitiveActivity,ToLink - Add type switch cases to the
IsNilfunction.
Types
Accumulate types for generated objects and add their types to the slices for:
ActorTypes: struct has Inbox/Outbox propertiesActivityTypes: struct has Actor/Object propertiesIntransitiveActivityTypes: struct has Actor property but no Object propertyLinkTypes: no ID property, but has a Href property.ObjectTypes: what’s left?
Accumulate types into the interfaces that can be used by generic code (Actors, Objects, etc).
The state machine
The ActivityPub state machine needs to operate the following:
- Validate received Activity.
- Determine which properties need to be dereferenced.
- Dereference properties and save them in local storage.
- Validate dereferenced objects.
- Persist flattened activity to storage.
- Operate Activity side-effects.
- Aggregate recipients.
- Dereference recipients.(?)
- Disseminate to local recipients.
- Disseminate to remote recipients.
Data types
We need some interfaces that unifies behaviour between client to server and server to server logic.
We should establish if the current authorized actor needs to be part of the API, or we can leave it as an implementation detail.
The implementations for the Processor and Validator would be scoped per each section of the specification:
- one for client to server for activities received in outboxes
- one for server to server for activities received in inboxes
// dereferencer is a helper interface that gets used
// by the [Validator] to enrich an activity with additional information.
type dereferencer interface {
// Maybe Load instead to keep it similar to readStore?
// (but without the filters?)
Fetch(iri vocab.IRI) (vocab.Item, error)
}
// disseminator is a helper interface that gets used
// by the [Processor] to submit activities to recipients.
type disseminator interface {
ToCollection(colIRI vocab.IRI, it vocab.Item) error
}
// readStore is a helper interface that gets used
// by the [Processor] or [Validator] to retrieve
// objects and activities from *local* storage.
type readStore interface {
Load(iri vocab.IRI, ff ...filters.Check) (vocab.Item, error)
}
// readStore is a helper interface that gets used
// by the [Processor] to save objects and collections to *local* storage.
type writeStore interface {
// Save saves the incoming ActivityStreams Object, and returns it together with any properties
// populated by the method's side effects. (eg, Published property can point to the current time, etc.).
Save(vocab.Item) (vocab.Item, error)
// Delete deletes completely from storage the ActivityStreams Object, this is usually
// a side effect of an Undo activity.
Delete(vocab.Item) error
// AddTo adds "it" element to the "col" collection.
AddTo(vocab.IRI, ...vocab.Item) error
// RemoveFrom removes "it" item from "col" collection
RemoveFrom(vocab.IRI, ...vocab.Item) error
}
// store is a helper interface that gets used
// by the [Processor] or [Validator] to retrieve and/or store
// objects and activities from *local* storage.
type store interface {
readStore
writeStore
}
type Validator interface {
// ValidateActivity validates an activity.
// It dereferences all properties that need to be dereferenced and validates it.
// The "it" parameter gets enriched with the dereferenced properties.
Validate(ctx context.Context, it vocab.Item) error
}
type Processor interface {
// Process processes the incoming activity
// The "it" parameter gets enriched with whichever additional information operating
// the activity adds.
// Eg. In the case of a Create activity operated in an outbox collection, its Object
// would receive an ID, or the Published property gets added if they're missing.
Process(ctx context.Context, it vocab.Item) error
}