diff options
authorbrent s <>2017-11-27 00:09:10 -0500
committerbrent s <>2017-11-27 00:11:22 -0500
commit5e3c551317dc7715756f8296d9943f2681681501 (patch)
parentbd83b918bcd53ddc997ef849d8af91963dcd0043 (diff)
hooo boy. draft 1 done, now seeking limited peer review.
-rw-r--r--README.txt (renamed from README)6
-rw-r--r--relspec.xsd (renamed from reslspec.xsd)0
5 files changed, 366 insertions, 36 deletions
diff --git a/README b/README.txt
index 9617782..82c031b 100644
--- a/README
+++ b/README.txt
@@ -5,6 +5,9 @@ ALPHA RELEASE
This document and related files are intended to serve as a universal method for
announcing new software releases.
+For the full specification, please reference SPEC.txt. For an example of
+implementation, please reference samplefeed.xml.
See the COPYING file and accompanying texts in licenses/.
@@ -44,6 +47,7 @@ a new release is pushed.
Splitting of the upstream project into separate channels is at the discretion of
the upstream, but separate projects should be placed in different feeds.
+For the full specification, see the SPEC.txt file.
The author recommends the following to provide the most efficient and optimal
@@ -79,4 +83,4 @@ Depending on how many releases you track in a feed's channel, one can increase
responsiveness of their feed by ensuring a maximum number of items (and thus
decreasing the amount of data the client(s) need to fetch to check for new
releases, and decrease the overall bandwidth consumption of the upstream if by
-only a marginal amount). \ No newline at end of file
+only a marginal amount).
diff --git a/SPEC.txt b/SPEC.txt
new file mode 100644
index 0000000..3c9d78e
--- /dev/null
+++ b/SPEC.txt
@@ -0,0 +1,340 @@
+Universal Release Specification
+v 0.01
+There are certain conventions used in this document that are used to reference
+various components and attributes of URS ("Universal Release Specification").
+UPSTREAM: The author of software (typically the ones implementing URS).
+DOWNSTREAM: The software packager, user, etc. of software that UPSTREAM creates.
+MUST or REQUIRED: The element, attribute, etc. is *required* to be considered as
+ valid URS.
+SHOULD or RECOMMENDED: The element, attribute, etc. is not required, but is
+ *highly recommended* by the author. Typically, this is
+ to ensure good interoperability and/or clean and smooth
+ interoperability with packaging standards various
+ DOWNSTREAM projects have.
+MAY or OPTIONAL: The element, attribute, etc. is not required, and is not
+ explicitly recommended, but may be implemented at UPSTREAM or
+ DOWNSTREAM's discretion.
+SHOULD NOT or UNRECOMMENDED: The element, attribute, etc. is highly advised
+ against, as it may cause confusion, errors, and/or
+ other instabilities, or the feature is not per-spec
+ guaranteed to be available in all implementations
+ of URS.
+MUST NOT or RESTRICTED: The element, attribute, etc. must not, under any
+ circumstances, be implemented in the presented way, lest
+ breakage is certain to occur.
+The URS uses an RSS+XML-driven approach.
+RSS and XML have provided a proven and time-tested format of serializing
+metadata in a format that:
+* Provides minimal overhead
+* Is flexible and allows for easily adding new features over time as the scheme
+ matures ("future-proof").
+* Is widely accessible - it can be parsed as plaintext both by machine (via a
+ plethora of libraries already in existence) and human eyes (though you may
+ want to use an RSS reader client) - in fact, all proper "podcasts" found
+ today still use RSS+XML.
+* Is widely supported - one can easily use existing shared webhosting, or an
+ existing webserver, even an FTP server or NFS server to deploy.
+Because of the above, it was decided that RSS+XML would allow for the widest and
+easiest adoption.
+For an example of a complete and valid URS feed, refer to the samplefeed.xml
+file distributed with this specification.
+2.1 Feed
+2.1.1 Declaration
+An XML declaration header for a feed MUST be included. It MUST include:
+* The version (most likely 1.0)
+* The document encoding (most likely UTF-8)
+e.g. "<?xml version="1.0" encoding="UTF-8"?>"
+2.1.2 Root Element
+The root element of the feed MUST be named "rss". It MUST have the "relspec"
+namespace applied (via It SHOULD
+include the XSD as an XSI, to ensure complete processing by clients.
+e.g. <rss xml:lang="en" version="2.0"
+ xmlns:relspec=""
+ xmlns:xsi=""
+ xsi:schemaLocation=" relspec.xsd">
+2.2 Channels
+"Channels" are sections of a feed (section 2.1) that allows DOWNSTREAM to more
+easily track e.g. beta releases vs. stable releases, main projects vs. project
+add-ons, or the like. Specific implementation is at the discretion of UPSTREAM.
+2.2.1 UPSTREAM SHOULD NOT provide multiple separate projects in the same feed.
+2.2.2 UPSTREAM SHOULD use the following order priority for channel listings (if
+multiple channels are used):
+Stable main project releases
+Stable project addon releases (plugins, et. al.)
+Beta main project releases
+Beta project addon releases
+Alpha/development main project releases
+Alpha/development project addon releases
+Translation forks of the above
+Alternate release formats (i.e. .zip, .tar.bz2, .tar.xz, etc.) if different from
+ primary release distribution.
+2.2.3 Channel Elements
+Channel elements MAY be serialized in any order, but channel elements SHOULD be
+presented in the following order:
+* title (REQUIRED)
+* link (REQUIRED)
+* description (REQUIRED)
+* generator (OPTIONAL)
+* managingEditor (REQUIRED)
+* webMaster (REQUIRED)
+* pubDate (REQUIRED)
+* lastBuildDate (RECOMMENDED)
+* category (OPTIONAL)
+* language (RECOMMENDED)
+* copyright (REQUIRED)
+* ttl (OPTIONAL)
+* image (OPTIONAL)
+ Title Element
+The title of the channel MUST be a human-readable string that will easily
+identify what that channel tracks. It is REQUIRED.
+e.g. <title>FooBar - Stable</title>
+ Link Element
+The link of the channel MUST be the URL of UPSTREAM project's main website. If
+no website is available, it SHOULD be the URL of any documentation available. It
+If available, it SHOULD use HTTPS.
+e.g. <link></link>
+ Description Element
+The description of the project. This summarized description SHOULD NOT exceed
+128 characters. It is REQUIRED.
+e.g. <description>A program that does things.</description>
+ Generator Element
+The software used to generate/modify/maintain your feed. It SHOULD NOT exceed
+256 characters. It SHOULD include a URL for the generator software, if
+available. It is OPTIONAL.
+e.g. <generator> -</generator>
+ ManagingEditor Element
+The managingEditor element is used to specify the author of UPSTREAM, and used
+to contact for problems regarding the software itself. It is REQUIRED.
+e.g. <managingEditor>somename@somedomain.tld (Some Name)</managingEditor>
+ WebMaster Element
+The webMaster is the technological contact for the infrastructure *serving*
+UPSTREAM. This is the contact to use if e.g. there is a permissions problem in
+FTP, or the main website is inaccessible, etc. It MAY be the same contact as
+managingEditor. It is REQUIRED.
+e.g. <webMaster>anothername@somedomain.tld (Another Name)</webMaster>
+ PubDate Element
+The pubDate element contains information on when the content of the feed has
+changed. It MUST be in RFC 822 format. It is REQUIRED.
+e.g. <pubDate>Sat, 25 Nov 2017 20:30:00 GMT</pubDate>
+ LastBuildDate Element
+The lastBuildDate element indicates when the feed itself was last generated. It
+MUST be in RFC 822 format. It is RECOMMENDED.
+e.g. <lastBuildDate>Sat, 25 Nov 2017 20:30:00 GMT</lastBuildDate>
+ Category Element
+The category elements act as "keywords". UPSTREAM MAY specify multiple separate
+category elements. They SHOULD describe the function, purpose, etc. of the
+UPSTREAM project. There are currently no canonical categories, but this may be
+implemented in future reveions of this specification. A channel SHOULD NOT
+exceed 5 categories. It is OPTIONAL.
+e.g. <category>security</category>
+ <category>security/encryption</category>
+ Language Element
+The language element is used as an indication of what language the feed's fields
+(and UPSTREAM's documentation) is written in. It MUST be a value as supported by
+the original RSS 2.0 spec. The lists of valid values can be found at the
+following URLs:
+e.g. <language>en-us</language>
+ Copyright Element
+The copyright element is used to denote (despite the somewhat misnomer of name)
+the license of an UPSTREAM project. It MUST be one of the SPDX short identifiers
+as found at - if the UPSTREAM
+license is not listed in that list, it MUST be "custom" with one exception - if
+UPSTREAM project is under a proprietary license and UPSTREAM author retains all
+rights granted, it MUST be the string "proprietary". It is REQUIRED.
+e.g. <copyright>AGPL-3.0</copyright>
+Note: You may need to review the URL the license links to if a SPDX shorthand
+is not listed next to the name. e.g. as of date of this document's composition,
+the "eCos License version 2.0" license does not have a shorthand listed.
+Clicking on it, however, reveals in the URL "eCos-2.0" - thus, eCos-2.0 would be
+ Docs Element
+The docs element should be a link to UPSTREAM documentation for the channel's
+project. It is RECOMMENDED.
+e.g. <docs></docs>
+ TTL Element
+The ttl element is a length of time, in seconds, that DOWNSTREAM MAY want to
+cache the feed for. This is useful for projets expecting a great deal of clients
+tracking the feed/channel. It is OPTIONAL.
+e.g. <ttl>86400</ttl>
+ Image Element
+The image element is used to reference a logo, artwork, etc. representative of
+It contains three sub-elements:
+* title - The title of the artwork (REQUIRED)
+* link - A URI that the artwork should link to (RECOMMENDED)
+* url - The URL of the image so it can be fetched (REQUIRED)
+e.g. <image>
+ <title>FooBar Logo</title>
+ <link></link>
+ <url></url>
+ </image>
+2.3 Items
+"Items" are sections of a Channel (section 2.2) that contain information about a
+specific release.
+2.3.1 UPSTREAM MUST serve newest items at the *top* of a Channel's item
+2.3.2 Item Attributes
+Item attributes MAY be serialized in any order, but item attributes SHOULD be
+presented in the following order:
+* title (REQUIRED)
+* description (OPTIONAL)
+* enclosure (REQUIRED)
+* guid (REQUIRED)
+* author (OPTIONAL)
+* comments (RECOMMENDED)
+* relspec:sig (RECOMMENDED)
+* relspec:ver (REQUIRED)
+ Title Element
+Same as, but the name to use for a specific release. The string is at
+UPSTREAM's discretion, but it is RECOMMENDED to use a format including the
+version number of this release. It is REQUIRED.
+e.g. <title>FooBar - Release 1.2.3</title>
+ Description Element
+Same as, but for a specific release. It is RECOMMENDED to include a
+summary or short list of highlights of this specific release. It is OPTIONAL.
+e.g. <description>Fixes security issues, segfaults</description>
+ Enclosure Element
+Perhaps the most important elements of the entire feed, the enclosure elements
+note where a file for a release can be fetched. Each item MUST include only one
+enclosure. It is REQUIRED.
+It MUST include three attributes: url, length, and type.
+* url - The URL of the release file (e.g. such as a "tarball", zip file, etc.)
+* length - The size of the file found at url, in bytes
+* type - The MIME type of the file found at url
+e.g. <enclosure url=""
+ length="5242880"
+ type="application/x-tar" />
+ GUID Element
+The guid element is used to uniquely identify elements in a machine-recognizable
+way. In URS, this MUST be a SHA512 sum of the file found referenced by the
+enclosure ( element's url attribute (this is to ensure data integrity
+in-transit). It MUST include the isPermaLink="false" attribute. It is REQUIRED.
+e.g. <guid isPermaLink="false">cf83e1357eefb8bdf15428...1a538327af927da3e</guid>
+ Author Element
+The author element follows the same convention as managingEditor (, but
+with the allowance of being unique to a release. This MAY be used for UPSTREAMs
+which employ a multi-person release team. See for more information. It
+e.g. <author> (Author Name)</author>
+ Link Element
+The link element contains a URL for full release notes for this release. It is
+e.g. <link></link>
+ Comments Element
+The comments element contains a URL for bug reports or other DOWNSTREAM feedback
+as it pertains to this particular release. If a specific release link is not
+available, it MUST be a link to the general bugtracker for UPSTREAM project. If
+this is not available, it MUST be a URL for a page with contact information. It
+e.g. <comments></comments>
+ Relspec:Sig Element
+The relspec:sig element is an extension element that provides a URL to a GnuPG
+or PGP detached-signature file (RFC 4880 § 7). It MAY be in either binary or
+ASCII-armored format (RFC 4880 § 6.2). It MUST NOT be a "clearsign"/"cleartext"
+signature. (RFC 4880 § 7).
+If the author ( element is specified, this signature MUST at
+least contain a signature from that email address. If it is not specified, this
+signature file MUST at least contain a signature from the managingEditor
+( element. It is RECOMMENDED.
+e.g. <relspec:sig></relspec:sig>
+ Relspec:Ver Element
+The relspec:ver element MUST be a string containing only the version number. It
+MUST be in Semantic Version ( format. If the UPSTREAM itself
+does not follow Semantic Version versioning schema, it is the UPSTREAM's
+responsibility to convert their native versioning to a Semantic Versioning
+compatible format for the feed to aid packagers. It is REQUIRED.
+e.g. <relspec:ver>1.2.3</relspec:ver> \ No newline at end of file
diff --git a/reslspec.xsd b/relspec.xsd
index e96fdc0..e96fdc0 100644
--- a/reslspec.xsd
+++ b/relspec.xsd
diff --git a/sample-scripts/ b/sample-scripts/
index 19e6424..b733e19 100755
--- a/sample-scripts/
+++ b/sample-scripts/
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from collections import OrderedDict
+from email.utils import parsedate_to_datetime as dateconvert
from urllib.request import urlopen
from humanize import naturalsize # not stdlib
@@ -40,22 +41,22 @@ class Release(object):
# This just saves some typing.
_title = c.find('title').text
_ver = c.find('relspec:ver', self.nsmap).text
- _releaseDate = c.find('pubDate')
+ _releaseDate = dateconvert(c.find('pubDate').text)
_description = c.find('description').text
_download = c.find('enclosure').attrib['url']
_size = naturalsize(int(c.find('enclosure').attrib['length']))
_mime = c.find('enclosure').attrib['type']
_sha512 = c.find('guid').text
_sig = c.find('relspec:sig', self.nsmap).text
- _notes = c.find('link')
- _bugs = c.find('comments')
+ _notes = c.find('link').text
+ _bugs = c.find('comments').text
releases[_ver] = {'title': _title,
'released': _releaseDate,
'desc': _description,
- 'donwload': _download,
+ 'download': _download,
'size': _size,
'mime-type': _mime,
- 'SHA512': _sha512,
+ 'sha512': _sha512,
'signature': _sig,
'release-notes': _notes,
'bug-reports': _bugs}
@@ -67,5 +68,11 @@ if __name__ == '__main__':
feed = Release(
for c in feed.channels:
print('\nChannel: {0}'.format(c.find('title').text))
- for r in feed.Releases(c):
- print(r)
+ releases = feed.Releases(c)
+ for r in releases.keys():
+ print('\t' + r)
+ for a in ('title', 'released', 'desc', 'download', 'size',
+ 'mime-type', 'sha512', 'signature', 'release-notes',
+ 'bug-reports'):
+ print('\t\t{0}: {1}'.format(a, releases[r][a]))
+ print()
diff --git a/samplefeed.xml b/samplefeed.xml
index 37b0c9b..e6d5e00 100644
--- a/samplefeed.xml
+++ b/samplefeed.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- See for more information -->
+<!-- See SPEC.txt for the full specification and an explanation of all fields. -->
<rss xml:lang="en" version="2.0"
@@ -11,27 +12,15 @@
<generator>Optional; name of software used to generate feed</generator>
<managingEditor>author@domain.tld (Name of software maintainer)</managingEditor>
<webMaster>admin@domain.tld (Name of website maintainer)</webMaster>
- <!-- This should change *every time the feed has new content*, RFC 822 format -->
<pubDate>Sat, 25 Nov 2017 20:30:00 GMT</pubDate>
- <!-- The last time this XML file was generated -->
<lastBuildDate>Sat, 25 Nov 2017 20:30:00 GMT</lastBuildDate>
- <!-- The author recommends the category field be used for functionality (e.g. "security", "operations", etc.) -->
- <!-- Must be one of the values in the following lists: -->
- <!--$16 -->
- <!-- -->
- <!-- The license of the software. This is a bit of a misnomer, but it's part of the vanilla RSS spec. -->
- <!-- Obviously it should be standardized. -->
- <!-- Use the shorthand (SPDX short identifier) as found in parentheses here: -->
- <!-- -->
- <!-- e.g. the Apache 2.0 license would be "Apache-2.0" -->
- <docs></docs>
- <!-- How long a client should cache the result of the feed in seconds. -->
+ <docs></docs>
<title>Software Logo</title>
@@ -43,24 +32,14 @@
<title>Software Name v1.2.3</title>
<description>Release v1.2.3, summary/highlights of changes</description>
<enclosure url=""
- length="1048576"
+ length="2097152"
type="application/x-gtar" />
- <!-- GUID must be a SHA512 checksum of the file referenced. -->
- <!-- This will not only guarantee unique identification of each item, but will also assist packagers. -->
- <guid>ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff</guid>
- <!-- If the software has multiple authors/builders/release team members, you can specifiy a specific one here. -->
+ <guid isPermaLink="false">ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff</guid>
<author>author@subdomain.tld (Author Name)</author>
- <!-- A link to the GnuPG/PGP signature. -->
- <!-- A version string - this should ONLY be the version string. -->
- <!-- This MUST follow strict SemVer (semantic versioning) schema: -->
- <!-- -->
- <!-- e.g. "1.30" becomes "1.30.0". "1.2+1" becomes "1.2.1". Alpha/Beta/RC releases should be placed
- in a separate channel dedicated to those types of releases. -->
- <!-- RFC 822 timestamp of release of software version -->
<pubDate>Sun, 26 Nov 2017 00:15:00 GMT</pubDate>
@@ -70,7 +49,7 @@
<enclosure url=""
type="application/x-gtar" />
- <guid>6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9</guid>
+ <guid isPermaLink="false">6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9</guid>
<author>author@subdomain.tld (Author Name)</author>
@@ -109,7 +88,7 @@
<enclosure url=""
type="application/x-gtar" />
- <guid>cb872de2b8d2509c54344435ce9cb43b4faa27f97d486ff4de35af03e4919fb4ec53267caf8def06ef177d69fe0abab3c12fbdc2f267d895fd07c36a62bff4bf</guid>
+ <guid isPermaLink="false">cb872de2b8d2509c54344435ce9cb43b4faa27f97d486ff4de35af03e4919fb4ec53267caf8def06ef177d69fe0abab3c12fbdc2f267d895fd07c36a62bff4bf</guid>
<author>author@subdomain.tld (Author Name)</author>
@@ -124,7 +103,7 @@
<enclosure url=""
type="application/x-gtar" />
- <guid>2257aab44b42813142aa8ac4767116ad5bd41e94a79aa0672cc962128ed4809f50ed38d35ba945a80799976c9efa9b686f28d18036134bc2bb0ac2de96ec6280</guid>
+ <guid isPermaLink="false">2257aab44b42813142aa8ac4767116ad5bd41e94a79aa0672cc962128ed4809f50ed38d35ba945a80799976c9efa9b686f28d18036134bc2bb0ac2de96ec6280</guid>
<author>author@subdomain.tld (Author Name)</author>