 Hi, welcome to Storing Web Assembly Modules with Bindle. I'm Matt Butcher and this I'm joined by Taylor Thomas and we are going to very quickly go through an overview of Bindle, an aggregate object storage system. So what do we mean when we talk about aggregate object storage? Well, the idea here is that we wanna store a collection of related objects under a named entry and with a single shared piece of metadata. So we want to be able to represent a group of objects as a single thing and represent the relationships between those objects in that group. As sort of an added bonus, we wanna be able to share when an aggregate has five objects and another aggregate has three objects and there's overlap. We wanna be able to share the objects in between so we're not constantly copying up the same things and that allows us to optimize for transmission, for caching and for reuse. So I put together a little diagram to sort of explain this idea. When we talk about object storage like Azure Blob Storage or Amazon S3 or Minio or something like that, we're typically thinking of this model where there's a single piece of metadata that has the name, the size, other attributes of that object and then a single binary object and the two of them are tightly related. We can think of other types of object storage that use similar models but might model with more than one object. So for example, the OCI registries and the image spec in which Docker images are stored, the idea there is you have one piece of metadata and then you have several different layers that can all be pulled down together and reassembled into one Docker container on the other side. Bindle is sort of one step beyond that where the idea is that we should be able to express more complicated relationships between objects. So it can represent things in more tree-like structure where we might have nine or 11 or 50 different objects but those objects can be related in different ways. And later on in this presentation we'll talk about grouping and feature flags as ways of indicating which particular objects within an aggregate object storage system we want to pull and how we want to configure them when we do. So I'm gonna pass on now to Taylor to talk us through the parts of Bindle. So how does all of this get expressed? So it looks like a kind of complex graph in our fun little clip art there in the beginning. And so what are the different parts of a Bindle? So let's go ahead and talk about the Bindle itself. So a Bindle, which we refer to in the lower case B to differentiate from the name of the project is the name for the package inside of the Bindle system. So we're talking the whole thing. This consists of two parts. First the invoice, which is the description of the Bindle that includes the metadata for it and a list of everything that should be attached to it and the parcels which are the objects related to that invoice. And that together makes a Bindle. So what's the invoice? An invoice is a description of the whole thing altogether. So it first has the top level metadata. So we're talking the thing you normally expect, name, version, the authors of it, any additional, there's also additional annotations that are allowed. Then you have a parcels list. And this is the list of each attached parcel which we'll talk about what makes up a parcel. And then each invoice can have a set of groups that gives you a way to organize different parts of the Bindle together. And there's also a section for signatures, which we'll talk a little bit more about in a second. Now, as for a parcel, a parcel in and of itself is just data. It can be anything, it's just bytes of some kind. And so the invoice actually lists all those parcels and how they're connected using a SHA. And then that SHA contains the, and then there's also other information like what kind of type it is, what you'd expect in most object storage systems. Now, what's interesting is that because it can be any arbitrary types of data, a Bindle could be used to represent something like a webpage and it would have a parcel for the HTML file, a parcel for the CSS file, a parcel for each image file, probably a parcel for the JavaScript file, all those things together. So in addition to this, we have this notion of features and groups as ways of describing the relationships between different objects inside of an invoice. So you might think of it this way, imagine we had an application that had both a web UI and a potential UI that could run on the desktop, right? A lot of the logic is the same. So you've got some sort of core resources that are in one group. And then you might have a group that has a web UI with the same kind of index.html and CSS files and things like that. Groups allow you ways to say, okay, these objects, these parcels belong here, these parcels belong here. And when you pull this one, these are the required relationships between this and when you pull that, these are the required relationships between those. Features are a little more special. Imagine like if you have a system where there's a GPU, you might wanna turn on a feature to take advantage of that GPU. Whereas on a platform without one, you might not want to turn on that feature. So features and groups together are tools to indicate a parcel's relationship to the Bindle itself and to the other parcels inside of that Bindle. Now quickly, I'll also talk about signatures. One of the important things that we wanted to make sure we could accomplish in this system was cryptographic provenance trails. So that you would always be able to say, okay, when I pull this assembly of objects, these are exactly the objects that the creator of this Bindle intended to be pulled together, right? And we wanted to do that a little more elaborately where you could say, I wanna ensure that somebody verified that these were the correct things and somebody hosted these and it's a host that I trust and somebody created it and it's a person that I know and so on. So we created a signature model that allows you to express relatively complicated signing chains and provenance chains so that in those cases where software supply chain security matters to you, there are a plethora of different ways that you can use this signature data to verify that things are as the original creator's hosts and verifiers intended them to be. So now we're gonna switch over to some examples and Taylor is gonna kick us off with the first one here. Yeah, so the examples part is really just, you might've gotten lost in that big fire hose of information we just gave you. So let's go ahead and talk about some very specific examples. So each example starting with this basic Bindle example, we'll have a link here at the top. You can click on that if you download the slides and you'll be able to see what the invoice actually looks like. So this first one is a very simple basic Bindle with none of the bells and whistles. This is just representing an example webpage. An invoice has a name that generally has some sort of arbitrarily pathy thing. So in this case, it's just called My Bindle and then a Semver compatible version. We won't go into Semver right now, but that's something that's very strong inside of Bindle that we use all the time. And you'll see that there are three separate parcels or files that are used here. So this is what we're talking about. There's an HTML file, a CSS file and a JavaScript file. Now these are all technically by default part of the default group, hence the name. And so I put a little box around to show there's a group, but there's no requirements here that are expressed. This is just, there's a Bindle and there's three files in this Bindle. There's no relationships defined or anything like that. This is a slightly more complicated example that illustrates how groups might be used. So now in Taylor's example, when an end user agent pulled that Bindle, the assumption is that it would pull all three parcels because they were part of the default group. Well, what if we have a situation where a particular Bindle maps a more sophisticated array of objects? So here's an example. My Bindle actually has both a client application in it and a server application in it. And we can represent these as separate groups, right? Then we might also even have a third group that has some utilities that could be used, that are additional command line tools that might be necessary in some situations, but not in others. So we've got some bright bold red arrows here to indicate when a relationship is required. And then we've got some pale arrows to indicate when it's not, when it's optional, right? So the idea here is we've got a group called a CLI group. It has two objects in it. So by default, when I pull this invoice and activate the CLI group, I will get those two first and second objects and they will be pulled down along with my Bindle. So those are two parcels that are gonna come in the Bindle. Now, if I wanna run a server, I might also want to turn on the server group. And turning that on will give me a daemon that I can run in the background, right? So if I turn on that group, then when my Bindle client pulls, it's gonna pull the server. But it is also going to pull the utility group because we can see that there's a requirement relationship between the daemon process and the blue box there at the bottom with the third item located inside of it. So what's illustrated here is this idea that you can have a single Bindle that encapsulates a more sophisticated application and you can model the relationship so that the agent can really pull a Bindle and pass in the configuration and be sure that the configuration it passes in. I need this group. I want this feature enabled, whatever. Will result in an application that the runtime can actually execute, whatever that runtime is. Now, we've been a little hand wavy about what the runtimes are, but I'm gonna hand it over again to Taylor to talk specifically about one of the runtimes that we intended to target with Bindle. Yeah, so last, just to finish this off as an example of using WASN nanoprocesses, which is the thing that's still in price we're not gonna talk about here. But the idea is what if you had a heavy and light example? So if you wanted to run, if you run a more powerful device or something else like a Raspberry Pi, you could run two different versions of something. So in this example weather app, we have something that's part of the default group that is just required because there's always something that must be pulled for something to run. And in this case, this is a weather.wasm. But that weather.wasm has a requirement of having some sort of almanac service to talk to. And this almanac group has one that's heavy and one that's light. And a runtime such as a wasm runtime could choose which one it needs based on the type of device it's actually running. So if you won't need that heavier thing, it's gonna give you more accurate results and you have the processing power to do it. It'll select, you can select one of the almanac group members. Or if you're running on a Raspberry Pi you could run the live almanac light. And so that's what these, they're both required in this case, but you're allowed to select from each group to be able to satisfy the requirements. So hopefully you've enjoyed this overview of Bindle very fast. If you're interested, please check it out. And we'd love to hear your feedback.