automating AGPL compliance

A webservice partially automating the publication of server side sources licensed under the AGPL was implemented for the cardstories game.
It could be reused in different contexts to help the occasional hacker to comply with the terms of the AGPL.

AGPL compliance

The primary reason for an author to use the AGPL instead of the GPL is to display a link to the server sources, as explained in the preamble:

…if your program is a web application, its interface could display a “Source” link that leads users to an archive
of the code. There are many ways you could offer source, and different solutions will be better for different programs;

When deploying an AGPL application server side, care must be taken to provide a way for the user to download the corresponding sources, including the local modifications:

Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software.

If the software is a webservice serving static files such as cardstories, the original sources could be included in an archive available at the same location ( for instance http://cardstories.dachary.org/cardstories/static/cardstories.zip ) and a link added in each page visible to the user.

republishing server sources

If someone implements a quick but useful hack in the code, the overhead of the compliance is comparatively high. For a few lines of patch in a python file, one would need to rebuild a source distribution. For cardstories It could be done as follows on Debian GNU/Linux :

cd /usr/share/pyshared/cardstories
git init
git add .
git commit -m 'archive modified version'
apt-get install --reinstall python-cardstories
git diff > /tmp/cardstories-hack.diff
cd /tmp
apt-get source python-cardstories
cd python-cardstories-*/cardstories
patch -R < /tmp/cardstories-hack.diff
apt-get build-dep python-cardstories
dpkg -i ../*cardstories*.deb

It is a fairly long sequence of commands and it requires a knowledge of Debian GNU/Linux packaging that may not be available, even to a seasoned python hacker.

automating the source archive creation

A new path was added to the webservice and builds an archive containing the server side sources from the installed files instead of using the source files from the original distribution. A first version was implemented in cardstories to collect the files that would not be visible if browsing the static tree served by the webservice, i.e.

  • site.py
  • service.py
  • tap.py

The code triggered by the /agpl path is as follows:

class AGPLResource(static.File):

    def __init__(self, directory, module):
        self.directory = directory
        self.module = module
        self.zipfile = module.__name__ + '.zip'
        static.File.__init__(self, self.directory + '/' + self.zipfile)

    def render(self, request):
        self.update()
        return static.File.render(self, request)

    def update(self):
        directory = os.path.dirname(self.module.__file__)
        archive = self.directory + '/' + self.zipfile
        f = zipfile.ZipFile(archive, 'w')
        for path in glob.glob(directory + '/*.py'):
            f.write(path, os.path.basename(path))
        f.close()

Further work

This automation only addresses a specific case of AGPL compliance. When more complex modifications are made to the software or its dependencies, there is a need for a careful update of the Complete and Corresponding Source.

This entry was posted in licensing. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>