owned this note
owned this note
Published
Linked with GitHub
# ActivityPub ZCAPs
aka activityCaps
## What?
## Prior Art
* ["OcapPub: Towards networks of consent"](https://gitlab.com/spritely/ocappub)
* There is an unfinished heading "Solving use cases in ActivityPub"
* herein we try to solve some using [ZCAP](https://w3c-ccg.github.io/zcap-spec/) for authorization
## TODO
* [ ] define `activityCaps` namespace and baseUri
* [ ] add "@context" to all the Example JSONs
## Simple: sending a direct message
![sequence diagram of activitypub inboxes and outboxes, each with GET and POST methods](https://www.w3.org/TR/activitypub/illustration/tutorial-2.png)
"Simple"
Assumptions:
* Ben is known by URI like `https://bengo.is` or `did:web:bengo.is`
* We have defined new terms
* `activityCaps:act`
* This is relation from an actor to the capability to act as the actor
* `activityCaps:post`
* This is relation from a resource to the capability that posts (sends) a message to the resource
* this scenario is for a service communicated with via HTTPS. Therefore, most URIs are https URIs. `did` URIs are only referenced via `sameAs` relationships, and should only need to be handled by did-aware clients.
* TODO: sketch this for invocations over non-https transports
### New Terms
#### activitypub-capabilities:act
This is relation from an actor to the capability to act as the actor
#### activitypub-capabilities:post
This is relation from a resource to the capability that posts (sends) a message to the resource
### Posting the message to the actor's outbox
#### `GET https://bengo.is`
```jsonld=
{
"id": "https://bengo.is",
"sameAs": "did:web:bengo.is",
"inbox": "/inbox",
"outbox": {
"id": "/outbox",
"apcap:post": "/outbox?capability=post",
},
"activityCaps:act": "?capability=act"
}
```
#### `GET https://bengo.is?capability=act`
```jsonld=
{
"content": "this capability represents being able to act as this actor, e.g. to 'post' things using activitypub tht are then attributedTo https://bengo.is. i.e. this may imply capability to write to this actor's outbox and to write to other activitypub servers' inboxes",
"invoker": "https://bengo.is",
}
```
#### `GET https://bengo.is/outbox`
The outbox has a post capability, which is referenced from the outbox using the `activityCaps:post` relation.
```jsonld=
{
"http:status": 401,
"content": "use POST or provide Authorization",
"activityCaps:post": "?capability=post"
}
```
#### `GET https://bengo.is/outbox?capability=post`
The outbox has a post capability. Who can invoke it? Well, the actor whose inbox it is.
```jsonld=
{
"content": "invoke this capability to post a message to the outbox",
"invoker": "https://bengo.is"
}
```
#### `POST https://bengo.is/outbox`
##### sans authorization
Request
```jsonld=
{
"type": "Note",
"content": "gm"
}
```
Response
```jsonld=
{
"http:status": 401,
"content": "Authorization is required. Try providing some."
}
```
##### with authorization via zcap-ld
Request
`.proof.creator` is a key uri which has a 'capabilityInvocation' [verification relationship] expressed in the DID Document found by resolving the did `did:web:bengo.is`. Remember, resolving `https://bengo.is` as JSON-LD shows a `owl:sameAs` relationship to `did:web:bengo.is`. i.e. we can follow from
* `https://bengo.is` `ap:outbox` ->
* `https://bengo.is/outbox` `activityCaps:post` ->
* `https://bengo.is/outbox?capability=post` `zcap:invoker` ->
* `https://bengo.is` `sameAs` ->
* `did:web:bengo.is` `did:capabilityInvocation` ->
* `did:key:bengo-keys:0` (which is the `creator` of the `zcap:proof`)
Questions
* Perhaps it would be clearer if I wrap this `Note` object in a `Create` activity. But I think AP requires the server to do that at some point anyway.
```jsonld=
{"@context": [
"https://example.org/zcap/v1",
"https://www.w3.org/ns/activitystreams"
],
"id": "urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4",
"to": "https://dustycloud.org",
"type": "Note",
"content": "gm",
"proof": {
"type": "Ed25519Signature2018",
"proofPurpose": "capabilityInvocation",
"capability": "https://bengo.is?capability=act",
"created": "2022-05-16T17:13:48Z",
"creator": "did:key:bengo-keys:0",
"signatureValue": "..."}}
```
Response
```jsonld=
{
"http:status": 201,
"location": "/urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4"
}
```
#### GET /urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4
This is the posted 'Create Note' activity.
Response
```jsonld=
{
"id": "urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4",
"result": "/notes/89c9b8aa-bb17-4b5d-8583-ad88fc2de3f6"
}
```
#### GET /notes/89c9b8aa-bb17-4b5d-8583-ad88fc2de3f6
```jsonld=
{"@context": [
"https://example.org/zcap/v1",
"https://www.w3.org/ns/activitystreams"
],
"id": "urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4",
"to": "https://dustycloud.org",
"type": "Note",
"content": "gm",
"proof": {
"type": "Ed25519Signature2018",
"proofPurpose": "capabilityInvocation",
"capability": "https://bengo.is?capability=act",
"created": "2022-05-16T17:13:48Z",
"creator": "did:key:bengo-keys:0",
"signatureValue": "..."}}
```
### Server-to-server Delivery
According to ActivityPub, Ben's server now wants to find a way of delivering this activity to dustycloud.org's server.
#### `GET https://dustycloud.org`
```jsonld=
{"id": "https://dustycloud.org",
"inbox": "/inbox"}
```
#### `GET https://dustycloud.org/inbox`
```jsonld=
{"activityCaps:post": "?capabilities=post"}
```
#### `GET https://dustycloud.org/inbox?capabilities=post`
* `delegationPolicy` is a relation I made up to describe the policy it will use to determine whether it will delegate to a potential `invoker`
```jsonld=
{
"delegationPolicy": {
"requireActorCapability": ["activityCaps:act"]
}
}
```
#### `POST https://dustycloud.org/inbox`
Noteworthy
* we encourage activitypub inbox to allow POST via proof of capabilityInvocation of the capability that has the `activityCaps:act` relation from the actor
Request to `https://dustycloud.org/inbox`
```jsonld=
{"@context": [
"https://example.org/zcap/v1",
"https://www.w3.org/ns/activitystreams"
],
"id": "urn:uuid:ad86eb2c-e9db-434a-beae-71b82120a8a4",
"to": "https://dustycloud.org",
"type": "Note",
"content": "gm",
"proof": {
"type": "Ed25519Signature2018",
"proofPurpose": "capabilityInvocation",
"capability": "https://bengo.is?capability=act",
"created": "2022-05-16T17:13:48Z",
"creator": "did:key:bengo-keys:0",
"signatureValue": "..."}}
```
Also considered:
* ways for the sending server to request delegation of the 'post to inbox' capability from the receiving server, perhaps with a specific caveat of a specific message.
* this is not preferred as it might end up being too different from TR ActivityPub server-to-server protocol. Maybe not that big a deal. Instead of POST fwded activity to /inbox, POST invocation to /inbox?capability=post
## Curating a photo collection
## Rights amplification for reply control
* Question: What does this mean?
## Controlling who can send you messages
* do you really need to do this? Is it enough to only process messages in the inbox that have `proof` of invocation of `activityCaps:act` of actors that are in a set of actors controlled by 'you'?
## Managing a mailing-list like Group
## Creating an Identifier
### `POST /identifiers`
Request
```jsonld=
{
"controller": "did:method:identifiers:0:controllers:0"
}
```
Response
* HTTP
* status: 201
* location: /identifiers/did\:key\:identifiers:0
```jsonld=
{
"url": "/identifiers/{uuid}"
}
```
### `GET /identifiers/{uuid}`
This is a did doc.
It's intended that `did:web:{host}:identifiers:{uuid}` resolves to this did doc. That may not be possible. The identifier may or may not support updates to its referent. If not, it may just be a `did:key`.
Response
```jsonld=
{
"id": "/identifiers/{uuid}",
"controller": "did:method:identifiers:0:controllers:0"
}
```
## Creating an Actor
### `POST /actors/`
Request
```jsonld=
{
"controller": "did:web:bengo.is",
"parts": ["https://activitypub.com/parts/actor"]
}
```
Response
* HTTP
* status: 201
```jsonld=
{
"url": "/actors/did:key:actors:0"
}
```
### `GET /actors/{did}`
Response
* HTTP
* status: 200
```jsonld=
{
"id": "/identifiers/{did}",
"sameAs": "{did}",
"inbox": "/actors/{did}/inbox",
"activityCaps:act": "/actors/{did}/capabilities/act"
}
```