2014-03-10

Verbs and Nouns in Activity Streams

While the Activity Streams data format is generally intended to provide machine readable descriptions of past, present or future events, those of use who use the format often have the need to translate those machine readable statements into human readable ones. For example, the following:


{
  "actor": {
    "displayName": "Joe"
  },
  "verb": "give",
  "object": {
    "objectType": "book",
    "id": "http://example.org/books/123",
    "displayName": "Moby Dick"
  },
  "target": {
    "displayName": "Sally"
  }
}

Can be translated into the English sentence, "Joe gave Sally the book 'Moby Dick'"; or, more generally, "Joe gave Sally a book". As we all know, there are several alternative forms that all express the same idea (some clearly less desirable than others): "Joe gave a book to Sally", "The book, 'Moby Dick' was given to Sally by Joe", "Sally received a book from Joe", and so on.

Exactly how an Activity Statement is translated into English depends entirely on the characteristics of the statement, the object types used and the verb. The Activity Streams vocabulary and structure has been intentionally left wide open to allow for a great deal of flexibility in how it is used. Unfortunately, this flexibility causes a great deal of ambiguity and difficulty when summarizing statements using natural language. This difficulty is increased significantly when we take extension verbs and objectTypes into consideration. To help deal with these ambiguities, I have been kicking around the notion of introducing formal linguistic characteristics to the "verb" and "objectType" definitions in Activity Streams 2.0.

If you look at the current AS 2.0 specification draft, you'll see that the "verb" and "objectType" properties have been reimagined as "Type Values". A "Type Value" is represented as either an implicit or explicit object. Implicit object type values are represented as Strings that contain either a simple token (e.g. "post") or an absolute IRI (e.g. "http://example.org/verbs/post"). Explicit object types values are represented directly as JSON objects.

For example:


  {
    ...,
    "verb": "post",
    ...
  }

Here, the verb "post" is semantically equivalent* to:


  {
    "verb": {
      "id": "post"
    }
  }

(* there is a caveat here in that simple token verbs such as "post" MUST always be represented in String form... so while "verb":"post" is equivalent to "verb":{"id":"post"}, only the former can be used within an Activity Streams 2.0 document. This is because the "id" property value is always required to be an absolute IRI.)

What this essentially means is that all verbs (and objectType's) are first class objects within Activity Streams and can have their own properties and characteristics. For example, a verb can have a "displayName":


  {
    "verb": {
      "id": "http://example.org/verbs/foo",
      "displayName": "Foo"
    }
  }

A Type Value's characteristics can help an implementation figure out what exactly the type value means and how to use it. This, for instance, comes in handy when we want to associate an extension objectType with an existing semantic model:


  {
    "objectType": "objectType",
    "id": "http://example.org/foo",
    "@type": "http://schema.org/Person"
  }

In this case, we are using the Activity Streams 2.0 JSON-LD alignment (the "@type" property) to indicate that extension objectType "http://example.org/foo" is a realization of the Schema.org Person type.

The "Linguistic Characteristics" of a verb and objectType are the collection of properties that describe how those objects are used within a natural language. For verbs, these characteristics include things like valency, conjugation regularity, tense, aspect and modality. For objectTypes, they include concepts such as countability, gender, collectiveness and animation. By understanding these characteristics, we can better interpret (and express) exactly what information is conveyed within an Activity Statement.

Let's start with verbs.

While the specific form and conjugation of verbs vary greatly from one language to the next, the type and function of verbs is generally universal. There are, for instance, Intransitive Verbs (verbs that only require a subject, such as "I walk", "He is walking", "You walked", etc), Transitive Verbs (those that have both a subject and a direct object, such as "Joe read the newspaper", and Ditransitive Verbs (those that have a subject, direct object and indirect object, such as "Joe gave the money to Sally"). There are also Linking Verbs ("Joe became worried") and Existential verbs ("Joe is alive", "Mike was here", etc).

Within the Activity Streams format, we are primarily concerned with Intransitive, Transitive, Ditransitive and Existential verb forms that may or may not be expressed in terms of tense or aspect. In other words, using Activity Streams 2.0, we can express concepts such as "Joe lives", "Joe is running", "Joe wrote a letter", and "Joe gave a book to Sally" but generally not statements such as "Joe became worried". (Note that, in very rare cases, it is possible for an Activity Statement to convey avalent verbs, that is verbs with no actor, object or target. I'll discuss these cases later.)

In order make it easier to comprehend the use of verbs within an Activity Stream document, I am exploring the ability to explicitly mark the linguistic characteristics of verbs within the Type Value definition. For instance:


  {
    "objectType": "verb",
    "id": "http://example.org/verbs/sneeze",
    "displayName": "sneeze", 
    "linguistic": {
      "en": {
        "infinitive": "sneeze",
        "category": "semelfactive",
        "flags": ["intransitive"]
      }
    }
  }

Here, the verb identified as "http://example.org/verbs/sneeze" is assigned the infinitive English-language root "sneeze". It is defined as a semelfactive verb with the intransitive characteristic. This essentially means that Activity Statements using this verb will not contain an "object" property, and that the "startTime"/"endTime" properties (if present) will be the same (the event was instantaneous).


  {
    "actor": {
      "displayName": "Joe"
    },
    "verb": "http://example.org/verbs/sneeze",
    "startTime": "2014-12-12T12:12:12Z",
    "endTime": "2014-12-12T12:12:12Z"
  }

It is possible for intransitive verbs to have an indirect object (the "target" of the action). For instance:


  {
    "objectType": "verb",
    "id": "http://example.org/verbs/sit",
    "displayName": "sit",
    "linguistic": {
      "en": {
        "infinitive": "sit",
        "category": "activity",
        "flags": ["intransitive"]
      }
    }
  }

  {
    "actor": {
      "displayName": "Joe"
    },
    "verb": "http://example.org/verbs/sit", 
    "target": {
      "objectType": "chair"
    },
    "startTime": "2014-01-01T12:00:00Z"
  }

Note that in this example, there is a startTime but no endTime. Because the "sit" verb is defined as belonging to the "activity" linguistic category, it is assumed to be durative (occurring over time) without having a natural end point. In other words, the above statement indicates that Joe is currently sitting on a chair (the target).

In most cases, verbs used in Activity Statements will be "transitive" (actor+object) and/or "ditransitive" (actor+object+target).


  {
    "objectType": "verb",
    "id": "http://example.org/verbs/approve",
    "displayName": "approve",
    "linguistic": {
      "en": {
        "infinitive": "approve",
        "category": "semelfactive",
        "flags": ["transitive"]
      }
    }
  }

  {
    "objectType": "verb",
    "id": "http://example.org/verbs/upload",
    "displayName": "upload",
    "linguistic": {
      "en": {
        "infinitive": "upload",
        "category": "accomplishment",
        "flags": ["transitive","ditransitive"]
      }
    }
  }

"Joe approved the proposal":

  {
    "actor": {
      "displayName": "Joe"
    },
    "verb": "http://example.org/verbs/approve",
    "object": {
      "objectType": "proposal"
    } 
  }

"Joe uploaded the proposal to the server":

  {
    "actor": {
      "displayName": "Joe"
    },
    "verb": "http://example.org/verbs/upload",
    "object": {
      "objectType": "proposal"
    },
    "target": {
      "objectType": "server"
    }
  }

While it is perfectly legal to use these verbs in an intransitive sense ("The file uploaded", "The proposal was approved"), doing so using the Activity Streams format is generally not going to be all that useful.

Note that the "linguistic" property examples below are all scoped to the "en" language tag (English). This allows us to specify distinct handling of verbs depending on specific language context -- that is, while a specific verb infinitive might use regular conjugation in one language, it may be irregular in another. If you end up needing to define some characteristics globally independent of language, but still define language specific characteristics, the special "*" language can be used:


  {
    "objectType": "verb",
    "id": "http://example.org/verbs/bake",
    "displayName": "bake",
    "linguistic": {
      "*": {
        "category": "accomplishment",
        "flags": ["transitive"]
      },
      "en": {
        "infinitive": "bake"
      },
      "de": {
        "infinitive": "backen",
        "present": "backt",
        "perfect": "gebacken",
        "passive": "gebacken",
        "imperfect": "backte",
        "flags": ["irregular"]
      }
    }
  }

In this case, when dealing with an English language context, we can determine that the verb "http://example.org/verbs/bake" is a regularly conjugated, transitive accomplishment (i.e. "baked", "baking", "have baked", "will bake", etc). However, when dealing with a German language context, the verb is handled as irregular with specific conjugations given.

Within the linguistic property, the possible values for "category" are:

  • activity
  • accomplishment
  • state
  • achievement
  • semelfactive

These correlate to the generally accepted Lexical Aspects of all verbs (that is, they describe how the verb relates to time).

The "flags" property value is an array containing one or more of:

  • intransitive
  • transitive
  • ditransitive
  • irregular
  • idiomatic

The flags are cumulative. For instance, a verb marked as being "intransitive" and "transitive" can be used with or without an "object" property in the Activity statement.

The "irregular" flag indicates that the verb forms are "irregular" in respect to default language-specific conjugation rules. Depending on the language context, additional properties may be specified that detail the specific conjugations.

The "idiomatic" flag indicates that the verb form is idiomatic. A common example of this is the verb "flag-as-inappropriate". Such verb forms do not have specific infinitives in the traditional sense, but are rather expressed in terms of a "verb phrase", i.e. "Joe flagged the post as inappropriate".

The "infinitive" property is used express the base form of the verb in any given language. This is also referred to as the "dictionary form". Verbs marked as being "idiomatic" will not typically include the "infinitive" property.

Verbs are only part of the equation, however. The nouns (objectTypes) are equally as important. For those, I propose an equivalent linguistic definition that capture characteristic such as countability, rationality, collectiveness and gender:


  {
    "objectType": "objectType",
    "id": "http://example.org/nouns/woman",
    "displayName": "woman",
    "@type": "http://schema.org/Person",
    "linguistic": {
      "*": {
        "flags": ["feminine","countable","rational"]
      },
      "en": {
        "root": "woman",
        "collective": "women",
        "flags": ["irregular"]
      }
    }
  }

  {
    "objectType": "objectType",
    "id": "http://example.org/nouns/man",
    "displayName": "man",
    "@type": "http://schema.org/Person",
    "linguistic": {
      "*": {
        "flags": ["masculine","countable","rational"]
      }, 
      "en": {
        "root": "man",
        "collective": "men",
        "flags": ["irregular"]
      }
    }
  }

To a native English speaker, the notion of gender specific treatment of nouns and verbs is a bit odd, as there are very few gender specific nouns in modern use (pronouns are a different story, of course). But in many languages, Russian for instance, nouns can be assigned specific gender qualities. The gender of a noun changes the structure of the natural language sentence that uses the noun. So if I have the existential Activity Statement:


  {
    "actor": {"displayName": "Mary"},
    "verb": "is",
    "object": {
      "objectType": "leader"
    }
  }

Absent any gender specific clues, I'd likely end up with a grammatically correct but semantically incorrect Russian translation: "Мария был лидером". If, however, we introduce the ability to specify gender clues, we can derive a proper feminine form translation: "Мария была лидером"


  {
    "actor": {
      "displayName": "Mary",
      "objectType": "http://example.org/noun/woman"
    },
    "verb": "is",
    "object": {
      "objectType": "leader"
    }
  }

The "flags" for objectTypes currently include:

  • irregular - nouns that are irregular in respect to language default plurality
  • feminimne - feminine gender
  • masculine - masculine gender
  • neutral - neutral gender
  • countable - nouns that have a plural form
  • uncountable - nouns that do not have a natural plural form
  • collective - nouns that have a collective aspect
  • rational - nouns that represent rational (sentient, animated, etc) constructs
  • abstract - nouns that represent abstract concepts
  • concrete - nouns that represent concrete concepts

As with verbs, the flags are cumulative. A noun that specifies generally mutually exclusive flags (e.g. "countable" and "uncountable") indicates that the noun can be used in both ways.

The "root" property is used to specify the root dictionary form of the noun. For irregular nouns, the "collective" property defines the specific plural form.

Now, there's a natural question here: if I'm using extension verbs, am I supposed to include this linguistic detail *EVERY* time I use the verb or objectType? The answer, of course, is: You can, but you don't have to.

By convention, one approach is to ensure that all of your extension verb and objectType identifiers use HTTP dereferencable URIs. For instance:


  {
    "actor": {
      "objectType": "http://example.org/nouns#woman",
      "displayName": "Sally"
    }
  }

If I've never encountered the "http://example.org/nouns/woman" objectType before, I have several options: 1) I can fallback to some default behavior specific to my implementation, 2) I can ignore it or 3) I could send an HTTP GET request to "http://example.org/nouns/woman" in an attempt to retrieve some information about that objectType. Something like:


GET /nouns HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Content-Type: application/activity+json

{
  "items": [
  {
    "objectType": "objectType",
    "id": "http://example.org/nouns#woman",
    "displayName": "woman",
    "@type": "http://schema.org/Person",
    "linguistic": {
      "*": {
        "flags": ["feminine","countable","rational"]
      },
      "en": {
        "root": "woman",
        "collective": "women",
        "flags": ["irregular"]
      }
    }
  },
  {
    "objectType": "objectType",
    "id": "http://example.org/nouns#man",
    "displayName": "man",
    "@type": "http://schema.org/Person",
    "linguistic": {
      "*": {
        "flags": ["masculine","countable","rational"]
      }, 
      "en": {
        "root": "man",
        "collective": "men",
        "flags": ["irregular"]
      }
    }
  } 
  ]
}

This approach allows implementers who are publishing new extension verb and objectType values to define those as reusable libraries that are incrementally discoverable by consuming applications without inflating the verboseness of the actual Activity Statements being passed around. The discovery step can happen asynchronously to the actual processing of the statement. And the result returned is durable and cacheable.

For now, that is all. Keep in mind that this is all just something that I've been kicking around. It's not yet a part of the core Activity Streams spec (I'll probably write it up as an extension draft). Any comments/feedback is welcomed and appreciated. There is a lot of work that would need to go into solidifying this idea.

2014-01-24

JSON id references

The JSON Pointer spec provides a great bit of functionality for referencing into the structure of a JSON document. For instance, if I have a bit of JSON like {"a":{"b":{"c":1}}}, I can create a JSON Pointer like "/a/b/c" to reference the value of "c". That's really a critical piece of functionality when referencing into a JSON document structure.

However, there is one important bit of functionality that JSON Pointer is missing, however: referencing JSON objects by ID the way we can in HTML and XML. The challenge, of course, is that JSON documents do not have a standardized "ID" attribute the way HTML and XML have. So let's define one.

Suppose we have the following JSON document at http://example.org/foo.json


{
  "items": [
    {
      "id": "a",
      "title": "foo",
      "child": {
        "id": "b",
        "title": "bar"
      }
    },
    {
      "id": "c",
      "title": "baz"
    }
  ]
}

The URL http://example.org/foo.json#$b denotes a reference to the object that contains "id": "b", regardless of where it appears within the overall document. To keep things simple, there are no parent/child/ancestor types of relationships. If there happens to be more than one object with "id": "b" in the document, the reference will be to all matching objects. Obviously, this reference syntax only allows referencing JSON objects.

The same approach works if the value of "id" is a number rather than a string:


{
  "items": [
    {
      "id": 1,
      "title": "foo",
      "child": {
        "id": 2,
        "title": "bar"
      }
    },
    {
      "id": 3,
      "title": "baz"
    }
  ]
}

The URL http://example.org/foo.json#$2 still just works.

But what if the value of "id" is not a JSON string or number? Well, then we just ignore it and assume we can't reference it.

But what if we're using a JSON variant like JSON-LD that uses it's own variation on "id" (JSON-LD uses "@id"). Well, in such cases, we can go ahead and assert that "id" and "@id" are equivalent as far as resolution is concerned. So if I happen to have:


{
  "items": [
    {
      "@id": "a",
      "title": "foo",
      "child": {
        "@id": "b",
        "title": "bar"
      }
    },
    {
      "@id": "c",
      "title": "baz"
    }
  ]
}

Then http://example.org/foo.json#$b still Just Works as expected.

Ok so that looks fine, but hold on a sec: In many JSON vocabularies that use "id" and "@id", the value of the identifier is a fully qualified URI in it's own right. It would suck if we always had to drop a full URL in as the value of a document fragment identifier. So for these cases, an alternative "anchor" attribute could be adopted. For instance:


{
  "items": [
    {
      "id": "http://example.org/Item/1A2B3C",
      "anchor": "a",
      "title": "foo",
      "child": {
        "id": "http://example.org/Item/123ABC",
        "anchor": "b",
        "title": "bar"
      }
    },
    {
      "id": "http://example.org/Item/ABC123",
      "anchor": "c",
      "title": "baz"
    }
  ]
}

To reference an object by it's anchor value, we'd use a slightly different syntax: "http://example.org/foo.json#@b". In the example above this reference is equivalent to "http://example.org/foo.json#$http://example.org/Item/123ABC". For consistency with JSON-LD, we could say that "anchor" and "@anchor" are equivalent.

Ok, so let's look at a practical example of this in action. Let's suppose I've got an Activity Stream that uses a new extension verb and object type. I want to make it possible to discover new and interesting things about the new verb and objectType. First, I would publish a JSON document that contains my verb and objectType definitions. Let's put this at http://example.org/types:


{
  "title": "My Activity Extensions",
  "items": [
    {
      "objectType": "verb",
      "id": "http://example.org/types#@plusone",
      "anchor": "plusone",
      "displayName": "+1",
      "alias": "like" 
    },
    {
      "objectType": "objectType",
      "id": "http://example.org/types#@article",
      "anchor": "article",
      "displayName": "An Article!"
    }
  ]
}

Then in my Activity statement, I could do:


{
  "verb": "http://example.org/types#@plusone",
  "actor": "acct:joe@example.com",
  "object": {
    "objectType": "http://example.org/types#@article",
    "displayName": "Thoughts",
    "id": "http://example.org/articles/1"
  }
}

When processing this Activity Statement, if the processor has never encountered the "http://example.org/types#@plusone" verb and "http://example.org/types#@article" objectType before, it could deference the URI, resolve the anchor and find out anything it needs to know from the reference.

Any thoughts?

2013-12-16

Activity Streams 2.0 Action Handlers

For review: Activity Streams 2.0 Action Handlers.

Co-authored with my friend and former IBM colleague Matthew Marum (now with SugarCRM), this draft introduces a number of new Activity Streams 2.0 "Action Handler" object types for use with the new Actions mechanism included in Activity Streams 2.0. These are essentially an evolution of several concepts including OpenSocial Embedded Experiences, Google's "Actions in the Inbox", the recent Schema.org "Actions" proposal, WebIntents, etc.

The best way to describe how this works is just to jump right into an example:


     {
       "objectType": "video",
       "displayName": "A Movie!",
       ...,
       "actions": {
         "watch": [
           {
             "objectType": "EmbedActionHandler",
             "displayName": "HD",
             "mediaType": "video/mpeg",
             "url": "http://cdn.example.org?id=123amp;fmt=HD",
           },
           {
             "objectType": "EmbedActionHandler",
             "displayName": "SD",
             "mediaType": "video/mpeg",
             "url": "http://cdn.example.org?id=123&fmt=SD",
           },
           {
             "objectType": "application",
             "displayName": "Watch on Netflix",
             "url": "http://netflix.com..."
           }
         ],
         "like": {
           "objectType": "EmbedActionHandler",
           "mediaType": "text/html",
           "url": "http://www.facebook.com/plugins/like.php...",
           "style": {
             "width": "150px",
             "height": "50px"
           }
         },
         "share": [
           {
             "objectType": "HttpActionHandler",
             "displayName": "Twitter",
             "url": "https://twitter.com/share?url=...",
             "target": "DIALOG"
           },
           {
             "objectType": "HttpActionHandler",
             "displayName": "Facebook",
             "url": "https://www.facebook.com/sharer/sharer.php?u=...",
             "target": "DIALOG"
           }
         ],
         "save": [
           {
             "objectType": "service",
             "id": "http://getpocket.com",
             "displayName": "Pocket",
             "context": {
               "url": "http://example.org/movie?id=123",
               "title": "A Movie!",
               "tags": "foo, bar, baz"
             }
           },
           {
             "objectType": "service",
             "id": "http://instapaper.com",
             "displayName": "Instapaper",
             "context": {
               "url": "http://example.org/movie?id=123",
               "title": "A Movie!",
               "selection": "An action movie!"
             }
           }
         ],
         "review": {
           "objectType": "HttpActionHandler",
           "displayName": "Rate this movie!",
           "url": "http://review.example.org/movie?id=123",
           "method": "POST",
           "expects": {
             "objectType": "HtmlForm",
             "mediaType": "application/x-www-form-urlencoded",
             "parameters": {
               "rating": {
                 "id": "http://schema.org/ratingValue",
                 "bestRating": 5,
                 "worstRating": 0,
                 "displayName": "Rating",
                 "required": true
               },
               "comments": {
                 "id": "http://schema.org/commentText",
                 "displayName": "Comments",
                 "required": "false"
               }
             }
           }
         }
       }
     }

Here, we have a simple "video" object with five specified "actions": "watch", "like", "share", "save" and "review". Each action is associated with one or more "action handlers". The handlers that have "objectType": "HttpActionHandler" describe HTTP request/response flows; the handlers that have "objectType": "EmbedActionHandler" describe embeddable content (e.g. embedding a video, or an OpenSocial gadget, etc). The handlers that have "objectType": "service" reference third party specific services (in this case Pocket and Instapaper, both of which have specific REST APIs that require customer keys, etc).

This is definitely still a work in progress that is far from being complete. As such, feedback and comments are definitely very welcome. Please direct any input you may have to the Activity Streams mailing list.

2013-11-06

Update to LINK/UNLINK Internet-Draft

I posted a fairly significant update to the LINK/UNLINK draft based on feedback received from Julian Reschke. There are several important changes.

One, in previous versions, link uniqueness was based on the tuple (context IRI, link relation, target IRI). In the current version, this is expanded to include all target attributes.

Two, previous versions of the Link draft did not adequately address the use of the Link header field's anchor attribute and the determination of the Context IRI. In the current draft, the Context IRI is resolved in accordance to Section 5.2 of RFC 5988. This allows the anchor attribute to be used to override the default context IRI.

This draft also deals with ambiguities in IRI comparison, 2xx response codes and conditional requests (well, I added the parts about condition requests in the previous iteration but had not specifically called those out as a change yet).

As always, feedback is requested and very welcomed.

2013-11-04

Evolving the urn:social Namespace

I've posted another update to the very draft "urn:social" Namespace definition. This fixes a few spec bugs but also expands the definition of the "urn:social:common" URN to allow for listing of specific common attribute dimensions. For instance, to reference the subset of a population sharing the same gender and approximate age, you could do something like "urn:social:common:gender;age". Or, to reference a subset sharing a history of similar activities, you could do something like "urn:social:common:history". The actual dimension tokens themselves are undefined. It would be up to implementations to define what those tokens are, what they mean and how they are to be used.

For a practical idea on how this would be used, consider sharing an article with members of a social network who are approximately the same age as you:


  POST /articles/joys-of-being-a-middle-aged-dad HTTP/1.1
  Host: example.org
  Link: <urn:social:common:age>; rel="to"

  ...

For the next iteration of the draft, I am considering the possibility of accommodating additional social network dimensions and relationship ties. Specifically:

  • urn:social:tie:evaluation:{dimension} --> refers to the subset evaluated by the context entity. For example:
    • urn:social:tie:evaluation:liked --> the subset of the population "liked" by the context entity
    • urn:social:tie:evaluation:disliked --> the subset of the population "disliked" by the context entity
    • urn:social:tie:evaluation:respect --> the subset of the population "respected" by the context entity
  • urn:social:tie:transaction:{role} --> refers to the subset sharing a specific transactional role with the context entity. For example:
    • urn:social:tie:transaction:customer --> the subset of the population considered to be a customer of the context entity
    • urn:social:tie:transaction:lender --> the subset of the population considered to be a lender to the context entity
  • urn:social:tie:affiliation:{dimension} --> refers to the subset sharing a common affiliation with the context entity. For example:
    • urn:social:tie:affiliation:employment --> refers to the subset affiliated by employment with the context entity (possible alternative: urn:social:common:employment)
    • urn:social:tie:affiliation:belief --> refers to the subset affiliated by belief system with the context entity (possible alternative: urn:social:common:belief)
  • urn:social:tie:interaction:{mode} --> refers to the subset that has interacted with the context entity. For example:
    • urn:social:tie:interaction --> refers to the subset that has interacted with the context entity in any mode.
    • urn:social:tie:interaction:chat --> refers to the subset that has "chatted" with the context entity.
    • urn:social:tie:interaction:email --> refers to the subset that has emailed the context entity.
  • urn:social:tie:familial:{role} --> refers to the subset sharing a familial relationship with the context entity. For example:
    • urn:social:tie:familial:spouse --> refers to the spouse/partner of the context entity.
    • urn:social:tie:familial:parent --> refers to the parent of the context entity.

These URNs would, quite admittedly, be very specialized. For instance, imagine sharing a post within a social network only with acknowledged members of your immediate and extended family, but only showing a notification to your parents and siblings.


  POST /images/pictures-of-my-son HTTP/1.1
  Host: example.org
  Link: <urn:social:tie:familial>; rel="scope" 
  Link: <urn:social:tie:familial:parent;sibling>; rel="to"

Or, sending an offer only to members of the community who have previously purchased items from you before, with specific notification given only to those who have "opted-in".


  POST /offers/1 HTTP/1.1
  Host: example.org
  Link: <urn:social:tie:transaction:customer>; rel="scope"
  Link: <urn:social:tie:interaction:opt-in>; rel="to"

Again, I'm just kicking these around and experimenting thus far, but it would be great to receive feedback on the overall direction. I know there's already a very rich history of work in the semantic web area around family history and structure, but the goal here is quite distinct from documenting the structure of a graph. Comments are more than welcome.

W3C Social Web Working Group

Introducing the W3C Social Web Working Group.

The Social Web Working Group will develop a Recommendation-track data-format to allow the transfer of social information, such as status updates, across differing social systems. This data format will be based on ActivityStreams and JSON in order to promote interoperability with Web Applications.

The Social Web Working Group may develop a Recommendation-track document that defines an API, based on OpenSocial, that lets developers embed of third party information with bidirectional communication inside Web applications. The focus will be on enabling the secure capabilities needed by social applications, which is necessary to bring areas such as social business to their full potential and avoid fragmentation.

The Social Web Working Group may develop a Recommendation-track Web protocol to allow the federation of status updates and other data, such as profile information, between heterogeneous Web-based social networking systems. This work will be based work on a federated social web explored both in HTTP (using Pubsubhububub) and XMPP.

The primary starting point of this WG will be the Activity Streams 2.0 draft... which will soon switch from being an Independently-Submitted IETF Internet-Draft to a W3C Note and eventual Recommendation. I have volunteered to continue serving as the editor for that specification. I will be posting weekly status updates (as much as possible at least) to both the Activity Streams mailing list and to this blog.

2013-11-01

Social Gestures and Link Relations

In the Activity Streams 2.0 spec work that I've been pursuing, I've been playing around with ways of bringing social gesturing together with first class links... blurring the lines between "verbs" and "link relations". One of the ideas I've been kicking around are a new collection of "Social Gesture Link Relations".

mentioned-by
-- refers to a resource mentioning the context
endorsed-by
-- refers to a resource that has positively endorsed the context
referred-by
-- refers to a resource referring to the context
liked-by
-- refers to a resource that has indicated a positive reaction to the context
disliked-by
-- refers to a resource that has indicated a negative reaction to the context
followed-by
-- refers to a resource that is following the activity of the context
saved-by
-- refers to a resource that has saved/pinned the context
shared-by
-- refers to a resource that has shared the context
reviewed-by
-- refers to a resource that has reviewed the context
purchased-by
-- refers to a resource that has purchased the context
owned-by
-- refers to a resource that owns the context
sold-by
-- refers to a resource that sold the context
shared-with
-- refers to a resource with whom the the context has been shared
endorsed-for
-- refers to a resource identifying a characteristic for which the context has been endorsed
visited-by
-- refers to a resource that has visited the context (example: social check-in)
earned
-- refers to an achievement earned by the context
earned-by
-- refers to a resource that has earned the context
issued-by
-- refers to the resource that awards the context to another
issued-for
-- refers to a resource identifying some action for which the context was issued
earned-for
-- refers to a resource identifying some action for which the context is earned

The use of these link relations ought to be fairly straight forward.

For example, suppose I want to list everyone who has endorsed a user for a variety of skills:


<html>
<body>
  ...
  <ul class="endorsements" >
    <li><a href="profile?id=1" rel="endorsed-by">John Doe</a>: for
      <a href="skills?id=1" rel="endorsed-for">Java</a>, 
      <a href="skills?id=2" rel="endorsed-for">Ruby</a>,
      <a href="skills?id=3" rel="endorsed-for">Python</a> 
    </li>
    <li><a href="profile?id=2" rel="endorsed-by">Jane Doe</a>: for
      <a href="skills?id=1" rel="endorsed-for">Java</a>
    </li>
  <ul>
  ...
</body>
</html>

In Activity Streams 2.0, we can reuse the same link relations:


{
  "objectType": "person",
  ...,
  "endorsements": {
    "totalItems": 2,
    "items": [
      {
        "objectType": "endorsement",
        "endorsed-by": {
          "url": "http://example.org/profile?id=1",
          "displayName": "John Doe"},
        "endorsed-for": [ 
          {
            "url":"http://example.org/skills?id=1",
            "displayName": "Java"
          },
          {
            "url":"http://example.org/skills?id=2",
            "displayName": "Ruby"
          },
          {
            "url":"http://example.org/skills?id=3",
            "displayName": "Python"
          }
        ]
      },
      {
        "objectType": "endorsement",
        "endorsed-by": {
          "url": "http://example.org/profile?id=2",
          "displayName": "Jane Doe"},
        "endorsed-for": [ 
          {
            "url":"http://example.org/skills?id=1",
            "displayName": "Java"
          }
        ]
      },
    ]
  }
}

Another basic example: We have a resource that represents an achievement of some sort (a "badge" for instance). We want to be able to describe who the badge is issued by, what it's issued for, and who it's been issued to:


{
  "objectType": "badge",
  ...
  "issued-by": "http://example.org/my-service",
  "issued-for": [
    "http://example.org/achievements?id=1",
    "http://example.org/achievements?id=2"
  ],
  "earned-by": [
    "acct:john.doe@example.org",
    "acct:jane.doe@example.org"
  ]
}

(Note: this is just a strawman.. for badges and achievements, some kind of alignment with stuff like Mozilla's "OpenBadges" project would be ideal.)

The remaining link relations ought to be fairly self-explanatory without needing to draw out examples of each.