ForgeFeed Specifications

Project Discovery via WebFinger

A project refers to a peice of software which may be spread across multiple code repositories. For example a consider a fictious programming language which may be composed of several components such as a compiler, a standard library, example codebases, a marketing website, etc. When the architecture of such a project spans multiple repositories then it is likely they should be represented as a project.

Sometimes however the scope of a project is much smaller such that it is entirely contained within one single repository, alternatively a large project might choose to version it's code all in one logical repository. If your forge supports it you MAY present a single repository as both an identifiable project and also a repository.

Project URI

A project URI identifies a software project and optionally the host that is resides on. The value serves to contain enough information such that a client with a simple URL parser may easily parse the identifier. A project URI MUST be a valid RFC7565 URI. The slug and hostname parts MUST match the URI path specification as defined in RFC3986-3.3 while the hostname, if specified, must match RFC3986-3.2.2.

project-uri = prefix slug hostname

prefix      = "project://"
slug        = rfc3986-path
hostname    = [@ rfc3986-hostname]

Slug

The Slug represents a unique string that identifies a project at a particular code forge.

Hostname

If the hostname part is missing then the address of the server receiving the query is assumed. For example the following two queries are equivalent:

https://example.org/.well-known/webfinger?resource=project://spartacus
https://example.org/.well-known/webfinger?resource=project://spartacus@example.org

Parsing

An example parser written in the Python programming language. Any programming language which implements a valid RFC7565 parser should be sufficent for reading a project URI.

from urllib.parse import urlparse

def parse_project(text):
    url = urlparse(text)
    if url.scheme != "project": # schema must be repository://
        raise Exception("Wrong scheme, should be project://")
    if not url.path:
        raise Exception("Missing slug part")
    split = url.path.split("@", 1)
    if len(split) == 2:
        domain = urlparse(f"ignore://{split[1]}")
        return (split[0], domain.netloc)
    return (split[0], None)

Relation Types

The following Relation Types are available for use within a project resource.

http://forge-feed.org/rel/avatar
http://forge-feed.org/rel/chatroom
http://forge-feed.org/rel/description
http://forge-feed.org/rel/label
http://forge-feed.org/rel/homepage
http://forge-feed.org/rel/repository
http://forge-feed.org/rel/mailing-list
http://forge-feed.org/rel/ticketing-system

http://forge-feed.org/rel/avatar

Forges that allow users to configure a logo can expose this information as an avatar for use in other applications.

{
  "rel": "http://webfinger.net/rel/avatar",
  "href": "https://example.org/stylized-logo.png"
}

http://feed-forge.org/rel/chatroom

A chatroom refers to an interactive chat environment for real time collaboration among project contributors.

{
  "rel": "http://webfinger.net/rel/chatroom",
  "href": "xmpp://spartacus@chat.example.org"
}

http://forge-feed.org/rel/description

A brief textual description which tells you something about the project.

{
  "rel": "http://example.org/rel/description",
  "titles": {
    "en-us": "A Text Adventure Written in FORTRAN 77",
    "es": "Una Aventura de Texto Escrita en FORTRAN 77"
  }
}

http://forge-feed.org/rel/label

A short text based category which can be used for searching.

{
  "rel": "http://forge-feed.org/rel/label",
  "properties": {
    "http://feed-forge.org/ns/label": "text-adventure"
  }
}

http://forge-feed.org/rel/homepage

Link to an HTTP representation of the project homepage.

{
  "rel": "http://feed-forge.org/rel/homepage",
  "href": "https://example.org/example/spartacus"
}

http://forge-feed.org/rel/mailing-list

Links to associated mailing lists, forms, etc.

{
    "rel": "http://feed-forge.org/rel/mailing-list",
    "href": "mailto://list-name@mail.example.org",
    "properties": {
        "http://feed-forge.org/ns/mailing-list-subscribe": "mailto://subscribe+list-name@mail.example.org",
        "http://feed-forge.org/ns/mailing-list-unsubscribe": "mailto://unsubscribe+list-name@mail.example.org"
    }
}

http://forge-feed.org/rel/ticketing-system

Links to issue tracking systems.

{
    "ref": "http://forge-feed.org/rel/ticketing-system",
    "href": "https://example.org/bugs",
}

http://forge-feed.org/rel/repository

Reference to a VCS managed code repository.

{
  "rel": "http://webfinger.net/rel/repository",
  "href": "https://code.example.org/spartacus/spartan-engine",
  "properties": {
    "http://forge-feed.org/ns/repository-uri": "repository:spartacus/spartan-engine",
    "http://forge-feed.org/ns/vcs-type": "git"
  }
}

Property Identifiers

The following property identifiers are available for use within a project resource.

http://forge-feed.org/ns/label
http://forge-feed.org/ns/repository-uri
http://forge-feed.org/ns/vcs-type
http://forge-feed.org/ns/mailing-list-subscribe
http://forge-feed.org/ns/mailing-list-unsubscribe

http://forge-feed.org/ns/label

A short text based category which can be used for searching.

http://forge-feed.org/ns/repository-uri

A Repository URI as described by the Repository URI specification.

http://forge-feed.org/ns/vcs-type

Identifies VCS types, valid strings are:

bzr (GNU Bazaar) bazaar.canonical.com
darcs (Darcs) darcs.net
fossil (Fossil) fossil-scm.org
git (Git) git-scm.com
hg (Mercurial) mercurial-scm.org
pijul (Pijul) pijul.org
svn (Apache Subversion) subversion.apache.org

http://forge-feed.org/ns/mailing-list-subscribe

Mailto link for subscribing from a mailing list.

http://forge-feed.org/ns/mailing-list-unsubscribe

Mailto link for unsubscribing from a mailing list.

Example Multi-Repository Query

A WebFinger query may be used to identify detailed information about a public project at a particular forge. Here is an example response about a fictitious project which has two code repositories associated with it as well as chat links, and a bug tracking system.

GET https://example.org/.well-known/webfinger?resource=project:spartacus
{
  "subject": "project:spartacus",
  "aliases": [
    "https://example.org"
  ],
  "links": [
    {
      "rel": "http://webfinger.net/rel/avatar",
      "href": "https://example.org/stylized-logo.png"
    },
    {
      "rel": "http://feed-forge.org/rel/homepage",
      "href": "https://code.example.org/spartacus"
    },
    {
      "rel": "http://forge-feed.org/rel/description",
      "titles": {
        "en-us": "A Text Adventure Written in FORTRAN 77",
        "es": "Una Aventura de Texto Escrita en FORTRAN 77"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/chatroom",
      "href": "ircs://irc.libera.chat/#spartacus-game",
      "properties": {
        "http://feed-forge.org/ns/chatroom": "irc"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/ticketing-system",
      "href": "https://example.org/bugs"
    },
    {
      "rel": "http://forge-feed.org/rel/label",
      "properties": {
        "http://feed-forge.org/ns/label": "fortran"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/label",
      "properties": {
        "http://feed-forge.org/ns/label": "text-adventure"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/repository",
      "href": "https://code.example.org/spartacus/spartan-engine",
      "titles": {
        "en-us": "The Spartan Game Engine"
      },
      "properties": {
        "http://forge-feed.org/rel/repository-uri": "repository:spartacus/game-engine"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/repository",
      "href": "https://code.example.org/spartacus/game",
      "titles": {
        "en-us": "Implementation of the Spartacus Text Adventure game"
      },
      "properties": {
        "http://forge-feed.org/ns/repository-uri": "repository:spartacus/game",
        "http://forge-feed.org/ns/vcs-type": "git"
      }
    },
    {
      "rel": "http://forge-feed.org/rel/repository",
      "href": "https://code.example.org/spartacus/game",
      "titles": {
        "en-us": "Promotional Website for the Spartacus Game"
      },
      "properties": {
        "http://forge-feed.org/ns/repository-uri": "repository:spartacus/www",
        "http://forge-feed.org/ns/vcs-type": "git"
      }
    }
  ]
}

Example Single Repository Query

Here is an example of a project with only a single repository associated with it.

{
  "subject": "project:fuu/bar",
  "links": [
    {
      "rel": "http://forge-feed.org/rel/repository",
      "href": "https://code.example.org/fuu/bar",
      "titles": {
        "en-us": "Baz Qux"
      },
      "properties": {
        "http://forge-feed.org/rel/repository-uri": "repository:fuu/bar",
        "http://forge-feed.org/rel/vcs-type": "git"
      }
    }
  ]
}

Security

Projects which are not publicly available should not be identifiable by making webfinger queries at all. A project which is private MUST return the same response as a repository which does not exist when making a webfinger request.

GET https://example.org/.well-known/webfinger?resource=project:example/spartacus
200
GET https://example.org/.well-known/webfinger?resource=project:example/private-project
404
GET https://example.org/.well-known/webfinger?resource=project:example/non-existent-project
404