Today the ml5.js team unveiled a proposal for a new license to impose ethical use requirements on their open source machine learning library. The community announcement is here. It is full of useful information about the context, purpose, and goals of the project so I encourage you to check it out. This post is intended to be a bit more focused on the license and license mechanisms themselves.

For context, ml5.js is a library that makes machine learning and artificial intelligence accessible to artists, creative coders and students. It is so easy to use that it even allows me to access things like style transfer and body tracking.

While access to powerful machine learning tools allows people to create amazing things, the ml5.js community also recognizes that it can be used for less socially productive applications. They reached out to the Engelberg Center and Tech Policy Clinic to see if there was a way to use their open source license to limit problematic uses of the library.

There is nothing new about attempting to introduce ethical obligations into open source software licenses. The conventional wisdom in open source software licensing today is that this is a bad idea. In part, this is due to the fact that it can be maddeningly hard to define ‘bad uses’ in a license in any robust, accurate way. In a way, this wisdom is codified in the fact that the Open Source Definition maintained by OSI (a prohibition against non-ethical uses would violate the “No Discrimination Against Fields of Endeavor” principle, among others).

Nonetheless, as the popularity of open source software has grown - and the community has become even more aware of the possible negative uses of software - there has been an increased interest in finding a way to mix ethical principles with an open source ethos. The Hippocratic License and Anti-Capitalist Software License are two recent examples.

Within this context, the ml5.js team decided to see if there was a way to bind its community to the ethical principles that they have worked hard to cultivate through the license on the software itself.

The ml5.js Approach

The proposed ml5.js approach relies on three main components:

  1. Separate the license from the community Code of Conduct
  2. Require recognition by a Code of Conduct Committee before a user is formally out of compliance with the Code of Conduct
  3. License ‘decay,’ so that the enhanced obligations of the license decay into a more standard MIT license after three years.

Separate the License from the Community Code of Conduct

One major challenge with attempting to impose ethical obligations via open source software licenses is defining ‘bad.’ Terrorists can become freedom fighters, industrial tools can be used for war, and general purpose code can be used to discriminate against vulnerable communities. Even if one could define ‘bad’ at the moment of drafting, the length of copyright term means that today’s definition would need to apply in 50 or 100 years.

The ml5.js approach separates the license from an evolving Code of Conduct. The license obligates users to comply with the rules established in the Code of Conduct. The Code of Conduct can evolve over time. Equally importantly, the ml5.js community (which tends to skew towards artists and away from lawyers) tends to be more comfortable interpreting and amending Codes of Conduct than licenses.

This approach comes at the cost of legal ambiguity. An activity that is allowed today might become prohibited three, five, or even ten years from now. The excuse provisions in the license itself, as well as the Code of Conduct Committee described below, are designed to mitigate that risk somewhat. Nonetheless, they do not eliminate it. Ultimately, the ml5.js team decided that they were comfortable potentially alienating edge cases in service of making a clear commitment to ethical uses.

Code of Conduct Committee Review of Violations

ml5.js is made up of commits from individuals contributors. Each one of them licenses their code to users under the license for the ml5.js repo. Any one of them could potentially accuse a user of violating the Code of Conduct, which would mean the user was violating the ml5.js license. That could mean that one contributor’s fringe interpretation of the Code of Conduct could disrupt uses that the majority of the ml5.js community found acceptable.

In order to reduce this risk, and to smooth the interpretation of the Code of Conduct, the license requires that a Code of Conduct Committee made up of members from the ml5.js community agree that a user is violating the Code of Conduct before they fall out of compliance with the license. Although this is not a guarantee that the Code of Conduct will be enforced fairly and in a way that matches the ml5.js community’s expectations as a whole, it will hopefully reduce the heckler’s veto that the ambiguous nature of ethical concerns introduce to the process.

License Decay

The extended term of copyright protection can make trying to create a new license dangerous. A poorly thought out license can create problems for decades into the future. The license decay provision of the ml5.js approach represents an attempt to reduce two types of that danger.

The ml5.js library is made up of thousands of individual commits by individual contributors. For the first three years of an individual commits’ existence, that commitment will be licensed under the heightened ml5.js obligations. After three years, that license decays into the widely-used MIT license.

The first danger that this mechanism addresses is what would happen if ml5.js was abandoned by the community. As long as ml5.js is in active development, the ml5.js library as a whole will contain commits that are less than three years old. That means that anyone using the library will be bound to comply with the Code of Conduct. However, if active development ceases, after three years the ml5.js library will no longer contain commits that require compliance with the Code of Conduct and the license will effectively revert to the MIT license.

Additionally, the ml5.js license assumes the existence of a Code of Conduct Committee and, implicitly, of a community that is regularly updating the Code of Conduct itself. If development of ml5.js stopped, it is also likely that the Code of Conduct Committee would stop operating. Decay helps avoid fights over the interpretation of the Code of Conduct well after the Committee has dissolved.

The second danger is simply that this exercise turns out to be a horrible idea. The three year period allows the community to change course. After three years the legacy of this wrong path will be more or less erased.

Will This Work?

Will this approach work? It is hard to say. It is certainly something different. The approach is much more restrictive than traditional open source licensing. It also requires more administrative overhead to operate. As of now, the ml5.js team believes that these costs are worth paying in order to make a strong commitment to ethical uses of the library. The comment period is open now. If you disagree, we would love to hear from you in the repo, on twitter, on Discord, or via email at feedback@ml5js.org.

Oh, and one last thing. Huge thanks to the Blue Oak Council for their model license. Doing something like this is hard, and doing it in a way that the community understands is even harder. Their easy-to-understand license formed the basis of the license we are using. That being said, they do not endorse this idea and any problems that it creates are ours alone.

Keep 3D Printers Unlocked (the comment)

Today I filed comments in support of my petition to expand the scope of the current rule that allows you to unlock your 3D printer and use the material of your choice.

As I explained earlier this year, we are in the middle of an every-three-year process whereby the U.S. Copyright Office gives communities permission to break DRM for specific purposes. In the past, the Copyright Office has included breaking DRM that locks 3D printers to materials from the printer manufacturer on its list.

In addition to requesting a renewal of the 3D printer exemption for the next three years, I also asked the Copyright Office to make two tweaks. The text of the current rule is:

Computer programs that operate 3D printers that employ microchip-reliant technological measures to limit the use of feedstock, when circumvention is accomplished solely for the purpose of using alternative feedstock and not for the purpose of accessing design software, design files, or proprietary data.

The first tweak was to replace feedstock with material. While both of these terms can be used to describe the stuff that printers use to make things, in the time since the original rule was written “material” has been more widely adopted by the industry and community. Updating the language will hopefully avoid any ambiguity in interpreting how it applies

The second tweak was to remove the microchip-reliant language from the exemption. I think that this qualifier is unnecessary. If a printer manufacturer uses DRM to limit third party material, and that DRM falls within the Copyright Office’s authority to regulate, the DRM should fit within the exemption granted by the Copyright Office. Leaving the additional language in the exemption just adds something else that people could litigate over, which would be a waste of everyone’s time.

What happens now? According to the Copyright Office’s website about this process, comments from anyone who opposes this modified exemption are due on February 9 (instructions for filing comments are on the website if you want to oppose it). Replies to those opposition comments (as well as comments from people who have an interest in the issue but do not take a side) are due March 10. If history is any guide, at some point after that the Copyright Office will hold hearings on the proposed exemptions. It is reasonable to expect the new rules by the end of 2021.

(Small) Suggestions for Reforming Copyright

Earlier this year, Senator Thom Tillis (who sits on the Senate Judiciary Committee, the committee that oversees copyright law) circulated a list of questions asking for input about ways to modernize copyright law. A number of organizations submitted extensive, substantive answers to these questions. Piggybacking on that work, I submitted a brief letter calling for two things.

First, I suggested that one way to modernize copyright law for the “digital age” would be to codify the rule that digitizing a physical object does not create a new copyright in the digitization itself. If you make an archival photograph of a Renaissance painting or a 3D scan of a dinosaur bone, you do not get a new copyright in the digital copy (copyright still applies to the original if it is protected by copyright).

The theory behind this rule is pretty straightforward. Copyright does not reward technical skill or effort. Instead, it attaches to creative works. By their very definition, digitizations of physical objects are designed to capture the work as accurately as possible. Injecting creativity into the process would work against that purpose.

This rule already exists in case law. A 1999 case recognized that photographic copies of public domain images do not get a new copyright because those reproductions do not involve original contributions. That logic was extended to 3D scans in 2008 in an opinion by then Judge (now Supreme Court Justice) Gorsuch. Both of these cases build on an earlier Supreme Court case that rejects a ‘sweat of the brow’ theory that would grant copyright in return for effort regardless of creative contribution. Article 14 of the EU’s new Copyright Directive is also designed to prevent at least some digitizations of public domain works from obtaining new copyright protection (here’s a good summary of that effort).

My letter asks Senator Tillis to integrate these conclusions directly into the text of copyright law. That would hopefully be a step towards ending the practice of cultural institutions attaching licenses (even CC licenses!) to digitized versions of objects in the public domain.

Second, I support a bill by Senator Wyden and Representative Lofgren to reform section 1201. This is the part of copyright law that governs DRM, and sets out the process whereby every three years we need to ask for permission to unlock 3D printers (among many other things).

It is strange that the entire unlocking 3D printers conversation happens in the context of copyright law. No one involved is worried that someone will pirate the software that runs 3D printers. Nonetheless, the current version of section 1201 could allow 3D printer manufacturers to use the fact that the printers run on software to prevent users from printing with third party materials.

The fix is simple enough - require a real nexus between a nominal violation of section 1201 and copyright law in order for liability to attach. If this reform was passed, it would likely eliminate the need to ask for permission to unlock 3D printers at all.

What happens now? It is hard to say. I do hope that my response makes Congress think more seriously about codifying the rule that digitizing an object does not create a new copyright. That will help keep the public domain in the public domain as we move into the digital future.

Creating a Live OSHWA Certification Map

With the recent release of the live OSHWA Open Source Hardware Certification API, I wanted to build a map that tracked the live distribution of certified open source hardware across the globe. You can see the map here. You can see the code here. This post explains how it all works.

The map I made is called a choropleth. It uses color intensity to compare the number of pieces of certified hardware between countries. I created it using leaflet.js. I chose leaflet mostly because I learned how to use it on a Coding Train tutorial. That tutorial also taught me how to access APIs, which is another piece of this project.

At a high level, creating the map involves a few steps:

  1. Download information from the OSHWA Open Source Hardware Certification API to get up to date information about all of the certified hardware.

  2. Add the number of pieces of certified hardware to the GeoJSON file. The GeoJSON file is the file that has the geometries for all of the countries so that they can be drawn on the map (and colored appropriately).

  3. Load the map.

  4. Add a layer on top of the map representing the number of pieces of certified hardware.

Downloading the Current Registration Information

The first thing you need to do for the map is get the current information about OSHWA certifications. Once you get an API key, you can look to the API documentation for example code that shows you how to access specific information in specific languages. For this map we are just going to get all of the OSHWA certified hardware projects.

In order to get the data, you can just copy the example code from the documentation. There are two things to keep in mind when you do this.

First, in order to actually get the data from the API into an object that is useful for javascript you need to parse it into a variable:

var data = JSON.parse(this.responseText);

Second, everything else in this code will happen in the place held by the console.log(this.responseText); in the example code. I think doing this causes everything to wait until the API data has been downloaded but I could be very wrong about that.

Unite the JSONs

Once you have the API data you need to combine it with the GeoJSON for the world. The first step is to create an object that contains the certified hardware count per country. That function is called in the var country_counter = countCountry(data); line. That calls the countCountry() function:

function countCountry(input_json) {
  //create a temporary dictionary in the function
  function_country_counter = {};
  //loop through all of the entries
  for (var i = 0; i < input_json.length; i++)
  {
    console.log(input_json[i]["country"]);
    var country = input_json[i]["country"];

    //this checks to see if the country is in the list
    let result = function_country_counter.hasOwnProperty(country);
    //console.log(result);

    //if the country is not in the dictionary
    if (function_country_counter.hasOwnProperty(country) == false) {
      //console.log('fffalse');
      //add the country with a count 1
      function_country_counter[country] = 1;
      //console.log(function_country_counter);
    }

    //if the country is in the dictionary
    if (function_country_counter.hasOwnProperty(country) == true) {
      //console.log('tttrue');
      //increment the counter
      function_country_counter[country] = function_country_counter[country] + 1;
      //console.log(function_country_counter);
    }
  }

  //return the tempoary dictionary
  return function_country_counter;

}

Once you have the countCountry() object, you can add it to the GeoJSON. The combineJSONs() function adds the HW_COUNT feature to the GeoJSON. It uses what seems like a comically inefficient process for doing this, but that’s what some person on stack overflow suggested and it worked, so…..

unction combineJSONs(country_list, geo_json) {
  console.log("hello");

  for (x in country_list) {

    //apparently the best way to add things to the geojson is to
    //loop over the entire thing every time to see if there is a match
    //and then add the entry when there is
    for (let i = 0; i < geo_json.features.length; i++) {
      // if the name of the country blob in the geo_json
      //being iterated upon equals x, which is the current country
      //from the country_list in the iteration
      if (geo_json.features[i].properties.ADMIN === x){
        //add a new elements that is HW_COUNT:<number of HW from the country_list>
        geo_json.features[i].properties["HW_COUNT"] = country_list[x]
        }
      }
    }

    //now loop over everything again and add a HW_COUNT of 0 to everything else
    for (let i = 0; i < geo_json.features.length; i++) {
      console.log(geo_json.features[i].properties.HW_COUNT);
      if (geo_json.features[i].properties.HW_COUNT === undefined){
        geo_json.features[i].properties["HW_COUNT"] = 0
      }
    }


    //prints the updated geojson
    console.log(geo_json);
    //returns the updated geojson
    return(geo_json);

  }

Now you have a combined_jsons object that has all of the geographic information for the countries and the information about how many pieces of hardware is certified in each country.

Make the map

At this point, everything basically follows the leaflet interactive choropleth tutoria. The only real changes I made were:

info.update = function (props) {
  		this._div.innerHTML = '<h4>OSHWA Open Source Hardware Certifications</h4>' +  (props ?
  			'<b>' + props.ADMIN + '</b><br />' + props.HW_COUNT + ' registrations'
  			: 'Hover over a country for registration count');
  	};

Updating this section so the title box talked about OSHWA

function getColor(d) {
    return d > 50 ? '#800026' :
        d > 20  ? '#BD0026' :
        d > 10  ? '#E31A1C' :
        d > 5  ? '#FC4E2A' :
        d > 1   ? '#FD8D3C' :
              '#FFFFFF';
  }

changed the thresholds and colors associated with those thresholds

function style(feature) {
  		return {
  			weight: 1,
  			opacity: 1,
  			color: '#d9d9d9',
  			dashArray: '3',
  			fillOpacity: 0.7,
  			fillColor: getColor(feature.properties.HW_COUNT)
  		};
  	}
layer.setStyle({
      weight: 1,
      color: '#666',
      dashArray: '',
      fillOpacity: 0.7
    });

slightly changed the weight and colors of the borders

map.attributionControl.addAttribution('Hardware Registrations from the <a href="https://certification.oshwa.org/">OSHWA Open Source Hardware Certification Program</a>');

changed the attribution light_number

var div = L.DomUtil.create("div", "legend"),
  			grades = [1, 5, 10, 20, 50],
  			labels = [],
  			from, to;

  		for (var i = 0; i < grades.length; i++) {
  			from = grades[i];
  			//to = grades[i + 1];
        to = (grades[i + 1]) - 1;

changed how the legend to match the other cutoffs.

That’s the long and short of it. I hope you take some time to play with the API and build a more interesting visualization than I put together.

Open Source Hardware Weather Report 2020

This post originally appeared on both the Engelberg Center and OSHWA blogs

Today the Engelberg Center, in collaboration with the Open Source Hardware Association (OSHWA) is thrilled to release the 2020 Open Source Hardware Weather Report. The report is a snapshot of the open source hardware community as it exists in 2020, ten years after the first Open Hardware Summit. It helps existing members of the open source hardware community take stock of where it is, and new members of the community understand the state of affairs today.

The open source hardware community has grown tremendously in the past decade. That growth is a testament to the viability of the idea of open source hardware. It can also create challenges when the community wants to talk to itself - let alone create welcoming pathways for new community members.

The 2020 report allows the open source hardware world to collectively identify what is working, share insights, and rally around shared challenges. It distills lessons learned and describes the collective understanding of the state of open source hardware. The report provides guidelines for how open source hardware can be a viable approach to hardware development, as well as identifies situations where open source hardware may not be the strongest approach. It also examines challenges that remain unresolved in 2020, along with opportunities for open source hardware in the future.

Like any weather report, this document is a snapshot of a moment in time. It was originally intended to flow from an in-person workshop held in connection with the tenth anniversary Open Hardware Summit here at the Engelberg Center. When the Summit went virtual, that workshop transformed into a series of interviews with a cross section of the open source hardware community.

Common themes, concerns, and challenges emerged during those discussions. The report provides an opportunity to summarize, distill, and universalize those insights. It makes it easier for the community to understand what is working in most places, and what challenges still demand our collective attention.

While this report is distilled from community input, it will also benefit from additional thoughts, concerns, and observations. That is why, in addition to the ‘stable release’ version captured in the PDF, we have also uploaded it to a github wiki. That is where we invite comments from the community, both on the substance of the report and on the form of the report itself. Let us know if a snapshot report is useful to you, and what we can do to make it more useful in the future.

Finally, thank you to everyone who took the time to contribute to this report. Some - but certainly not all - of them are listed in the acknowledgement section of the report. We also welcome outreach from other members of the community who did not participate this year, especially if they might be interested in participating in a future report.