Hi, my name is Christian Dildog Ryu and this is Katelyn Medis for Bowden. We are members of the Cult of the Dead Cow and here to present to you an unveiling of Veilid. We've been pumping this thing up for six months online, a lot of interesting stories about what it could and couldn't be. We're just ready to pull back the curtain a bit and talk about what is Veilid. So today we are about to drop some fantastic code. We're about to drop some really cool apps and things and we are about to make some cool announcements but I think above all I really hope that everybody understands that the biggest thing we're doing here is presenting an idea. And that idea is that some things are just worth doing even if it's not monetary. I think we all found ourselves in hacking for one reason or another and that was to make a difference, to do something that's worthwhile.  So we want to inspire all of you to hack the planet with us today. So in short, the Veilid mission, we exist to develop, distribute and maintain a privacy focused communication platform and protocol for the purposes of defending human and civil rights. There's a big mission there. We spent a lot of time thinking about this thing before we started writing code on it. We want to affect a particular outcome on the world. We're not interested in just writing cool code for the sake of it. We want to rethink the way applications are built so that the things people take for granted about application development change. You don't have to monetize everything. You don't have to sell users out just to make your cloud bill get paid. That kind of future is the future we should have had. So let's get into a little bit. Others have come before us. We had some inspiration from other tools. We looked at the world. We said we want to build things that are better. What tools exist already today? And Tor was there, front and center. I remember hanging out with Roger and Nick early in their development days and seeing how they had a similar mission to make things private that just weren't back in the day. I looked at IPFS, which is pretty novel in its use of distributed hash tables and all these crazy technologies to make interplanetary file systems. That just sounds huge, doesn't it? And there's a lot of other efforts in this space. Pewterpeer has been bounced around for 20 years since Napster and BitTorrent and everything else. We are at a time now where everyone has a supercomputer in their pocket. You got a terabyte of storage. And it begs the question, what if the cloud was everyone's computer, not just Jeff Bezos's? That's right. Valid is an open source, Pewterpeer mobile-first networked application framework. What this means is that it's like Tor and IPFS had sex and produced this thing, okay? Imagine a world where your apps can talk directly to each other, bypassing all the middlemen, not taking storage in the cloud or requiring some central authority for things like identity and storage or whatever. I looked at the Web 3.0 people and the things that are coming down the pipe there, there's been a lot of talk about decentralization lately. You've seen Mastodon and Blue Sky and these things, we're moving from centralized networks down to more feudal control. This is sort of the next logical step toward individual nodes all being peers in the same level, no hierarchy, but how do you affect that? How do you build that? How do you make it work? So here's what we're going to do. We put some design goals together for this project and obviously security was first. If you're going to be asking people to do something new with their applications and mobile devices, you have to be thinking like an attacker, how would you tear this apart? So security first, we wrote it in Rust, it is now over 100,000 lines of Rust, lovingly hand coded, built for memory and type safety. It runs everywhere, Rust is extremely portable. We have a core that runs on Linux, Mac, Windows, Android, iOS and in browser wasm today that works. We use standard internet protocols, you can think of this as an overlay network, so we're not going all the way down and writing a kernel, you know, but we're also not building on top of things like blockchains and, you know, transactional protocols and all this. We use UDP, we use TCP and we use WebSockets because these are the tools that are rock solid and available on all these platforms. It's all in network. We don't have external services, we don't rely on Google stun servers to do hole punching, we avoid DNS because that's a giant information leak. There's a tiny little bit of DNS, but we'll explain why that doesn't matter. And you know, we have all of the services that make VALID possible inside the VALID network itself, it's self contained. You just link it in, everything is working, all nodes are equal. Privacy focus was really important. When I looked at IPFS, it was not designed with privacy in mind. Tor obviously was designed with privacy in mind, but it wasn't designed with performance in mind and it was more about like proxying and it really enabled, you know, websites to talk, you know, to be reached anonymously, but that's not sort of a bi-directional privacy when, you know, the NSA runs 100 exit nodes, you know. So what if there were no exit nodes and in fact there were tens of millions of nodes? It would be really hard to monitor tens of millions of nodes instead of a couple exit nodes. So privacy focus from the beginning and keeping nodes and identities distinct. I'm going to get to why that's important and how we do it. Resiliency matters, you know, mobile networks, if you're going to be mobile first, you have to be able to handle networks that come and go, driving through the tunnel, losing your cell connection, coming onto a Wi-Fi, all of that. It's got to be able to context switch real fast. So we thought about all these things early on and we had to write code to support it. So feel free to cover this. So when we built this, we, when Dil first came to me with this idea, you know, he had the tech in his head, but what it really needed and I feel that this is really important and something that is often overlooked is the human side of things. What is the point of building these amazing technological, fantastic privacy things like Tor? If no one except for the people in this room understand how to use it. How does that benefit our parents? How does that benefit the people that might not be as comfortable with the internet? What we needed to do was really focus on what the user needs, how to make this approachable because, frankly, everybody deserves privacy. Everybody. Okay? When it came, you know, and not everything does need to be centralized. We've seen the problems with that. Human beings are flawed and they are going to, you know, put some of themselves into anything that they have control over. We've seen that with Mark Zuckerberg. We've seen that with Elon Musk. We want to make sure that this is something that no human imperfections can, you know, destroy. There's not going to be an algorithm. There's not going to be somebody pushing their ideals on you. This entire network is going to be what we all need it to be. All right. So let's start getting into the nitty gritty of how this works. All VALID nodes are applications running the VALID core. This means that no nodes are special, okay? There are no special nodes. You don't have to have an admin running servers or any kind of, you know, special. Everyone's running exactly the same thing. In fact, every application that is a VALID application looks the same to each other. So the network gains strength from a single popular app. Even for the less popular apps, they're all in the, the water level is raised by that one app that's very popular, right? So you don't have to build a really popular app and build your own VALID network. You can if you want. But the big VALID network is supported by the entire ecosystem, not just, you know, your app sailing away with a sea of eight users. So there's basically two kinds of uses today for the VALID core applications that are intended for end users and, well, headless nodes that could be used as a way to contribute to the network. If any of you guys that are Linux nerds like I am want to take the, what we're calling VALID server, it's not aptly named because it's not really a server per se. It's just VALID without any app. It's just running VALID, runs the RPC mechanism, passes data around. If you want to help the network out, the way you do it is by running that and just let it sit there. You don't have to do anything. You're not, you know, passing or passing encrypted traffic around and storing encrypted things to disk, and that's it. So today we have bindings for different languages. We're going to get to that. Again, the protocols are all low level. So UDP and TCP programmers that are writing apps can choose whether they want to talk over a more reliable sequenced protocol or if they would rather just have something be fast and unreliable.  There is a bootstrap mechanism. So this is the only time that we're going to use DNS. And that is when you turn your node on, it will make a few text message requests to bootstrap.valid.com. This pulls down some public keys and some dial information. I'll get into what a dial info is exactly, but you can think of it as an IP address with a little more augmentation. This gets you access to a few other valid nodes, just says, oh, by the way, the network's over here. And here's a public key that you can use to make sure that you're talking to the right nodes. You contact those nodes and download a chunk of routing table. And the valid server stores those routes and can then proceed to query all the other nodes in the routing table and find more routes. And it builds this routing table up and applies a distance metric, which is an XOR of a public key that is assigned to each node. Node generates a public key, private key pair. Nodes are identified by a public key. And the distance in the graph of nodes is measured by the XOR. It's sort of like, you know, if you were to subtract the nodes addresses, but XOR has that property where it doesn't matter, it's commutative, you know? So we use that for a nodal distance, and that's important later on. So all of the nodes do the same thing. So desktop apps reach out to Bootstrap, they download the routing table. The next time you launch it, it doesn't try to Bootstrap again. It tries to reach out to the previous nodes that it has talked to before. So Bootstrap operation is very lightweight. And assuming that you've talked to some nodes that are going to be long lived, it probably doesn't need to happen with every single time you switch into a valid app. Again, there's mobile apps and progressive web apps, and they all have slightly different network characteristics. But the first things that are going to happen is we're going to ask those Bootstraps to find themselves. And when I mean that, you're going to be finding nodes that are close to the Bootstraps and then close to yourself. We're going to be doing a NAT detection operation, which is somewhat like stun. You ever heard of stun? It's a detection of your public IP address, but also kind of tells you how you can be reached. It's a way of calculating what kind of NAT you're on. So your network address translation is like you're either fully firewalled or you have a full cone NAT or Porter address restricted NAT or symmetric NAT if you're on one of those weird carrier grade phone networks where every place that you go gives you a different IP address. Makes it a little more complicated. But valid nodes need to understand where they stand in the world. They need to understand how they could be reached from the outside and if they need any help. Achieving connectivity. So that operation happens very quickly at the beginning. About five seconds after a node starts up, it's figured out its public IP address from other nodes that it knows about and calculates its dial info. The dial info says, if I publish this to you, you'll be able to use this information to be able to reach me somehow. So basically we sign this information with that same public key for the node. That way when you pass it around, people can't forge your dial info and redirect your traffic by claiming that your dial info goes to somewhere else. No other overlay networks that I know of actually use signing on the routing table itself. They pass around a lot of information but nodes are just trusted to not modify it in transit. That doesn't really make sense to me. So all of the node information is signed and valid. So yes, network class detection determines if you are inbound capable or not.  Relays are used in that case. Every node in Valet is expected to relay encrypted traffic to the best of its ability to help out other nodes. So if a node is, say, a cell phone on a cell network going through a tunnel and it just can't receive inbound traffic, it's going to use a relay from the network to help get inbound traffic. It'll make an outbound connection and that relay's IP address is going to be part of its dial info as signed and published. So that way, you know, you don't have to relay forever and relays can start rejecting stuff and then the nodes will automatically pick a new one. So after that, you just have to know whether or not nodes are alive, whether or not they've continued to pass packets if they're still there. And we have an exponential back off mechanism of pinging those nodes over the same Bailey protocol to determine if nodes are still alive in the routing table. This turns out to be a statistical effort, almost entirely. You're really trying to understand the performance characteristics of other nodes and how alive they are. Should I talk to them? Can I trust them to keep being there? Turns out that if a node's been around for five minutes, chances are it's going to be around for another five. If a node's been around for half an hour, it's going to be around for another half an hour. It's just the math behind it, sort of. If a node's only been around for a couple seconds, you probably shouldn't be relying on it for, say, your private routing, because chances are it's going to just drop off soon. So we keep this math and we do it on a per node basis. So. All right. So what we're here to do with y'all is to help you inspire you to build stuff on this. I'm sure you can imagine after hearing all of that the many, many ways that this can be used and built upon. And I'm sure everyone is sitting there noodling over what projects could be built with this. Whether it's a peer-to-peer message or whether it's social media, the possibilities here are endless. And we really want to give you the tools to do that. All devices are going to be welcome and treated fairly. It's all equal. And then we're only as strong as the weakest node. Like every node is equal. And I think that's pretty cool. And yeah, you're welcome to use the Baylor network on its own or you can just build on it. And we really hope that everybody takes the opportunity to build on it. OK, so let's get into some deeper stuff. What is this cryptography that enables what we're doing here? Devil's in the details. And I know I've already had a ton of lovely, contrary conversations with all of you at some point. How does this actually function? OK, well, we have a cryptography suite that we have blessed for this project. We're calling it VLD0. I'll give you a hint. If we have to change it, it would be VLD1. We have a set of tools that we vetted. We did not roll our own crypto. We know better than that. But we're hoping to put things together that are known good. Authentication is done with ED25519 on Curve25519. So we have a very fast public-private key authentication signing system. All node IDs are effectively ED25519 nodes. Key exchange is done with the DH that is came on Curve25519 shortly after ED25519 was made. And yeah, so the same nodes can also be used to generate a symmetric key between nodes. So everything that if you have somebody's public key and you have your own secret key, you can DH those to produce a shared secret. Once you have that, you have to have a stream cipher or something to encrypt with that in an appropriate way. That is invalid. We're using the extended nonce version of Chacha 20 poly 1305, which is a stream cipher that comes with an AEAD built in. It is an associated data encryption system. So you can do things like partially encrypt a packet, include a header in the signing part, and have the signing identity as part of the encryption all in one go. You don't have to worry about do I sign first or do I hash Mac and all this other stuff? No, it's all just built in. You don't have to worry about it.  And then yeah, so message digesters are being done with the Blake 3, which again is a fast hash. It's extremely, extremely fast. Everything in this key space, by the way, is 256-bit. So all of these algorithms here are tuned for a 256-bit key space. And key derivation is done with Argon 2, which won the 2015 password hashing competition. And that is a very slow hash intended to slow down and stymie GPU-based attacks on passwords. So all of that is in the VLD0 suite for people to use as part of our framework. If we have to change things, though, VLD0 has been built with an upgradeable crypto system from the beginning. We recognized that cryptography is going to fail us through the advancement of technology, CPU speeds, memory availability, GPU attacks, whatever it is, differential, this, that, the other things. Stuff falls apart. We know that we'll have to change some of this down the line, so we built in the ability to upgrade the cryptography from day one. You don't have to understand necessarily every cryptographic decision that's being made. Every new version of our crypto system is supported alongside the old ones. So we can add a new crypto system, wait for it to become popular, and then deprecate the old one. Everything has typed keys as a result, so you know which crypto system was used with the key. We have migration support built in, so if data is persisted with an old crypto system, it can be automatically re-encrypted with the new crypto system. And we can use, again, simultaneous crypto systems to do transitional, have both of them alive at the same time. This enables a bunch of different kinds of storage. Valet has secure storage. We have completely cross-platform support for device-level secrets. So we're using iOS and MacOS keychains. We have the Android Key Store. We have Windows Protected Store, Linux Secret Service. We have a table store, which is an encrypted key-value database, so nothing needs to be stored at all on the file system without being encrypted. Keep all of those private keys in the Protected Store, encrypt everything to the table store, and then that enables the actual record store and block store, which are a distributed hash table and the content-addressable storage. So on the wire, everything, all these protocols use the same encryption. Everything is encrypted and signed. Everything is time-stamped, and all of the node information is signed. That means very little of what we do has an opportunity to be spoofed, and it really wouldn't matter if you did. So the reason that I am up here is because at one point, somebody got into my ex's phone, took some pictures out of it that I didn't wanna be shared, and they shared it online because my ex didn't understand the importance of his own privacy. He didn't understand how important it was to keep his phone locked. That is one reason that we really wanted to push that all of our storage is encrypted at rest. It's going to always be safe, no matter what. Like, unless they actually know how to get into everything, it doesn't matter. Like, it's going to be safe, and that is the point. We want to really address the fact that everybody, you know, we want everyone to understand the value of their privacy. That's part of this, is to understand what you're giving away and what you're trading in order to use a lot of these websites. Your data's protected even if you lose your device, and we're just making sure that everything's going to be safe, and things like what happened to me don't happen to other people. And I know I said I wasn't gonna drop any zero days or anything, but you really should do an iPhone backup of a lot of your popular encrypted messenger apps and take a look at what stuff is actually encrypted on disk because you might be surprised about that. Okay. RPC protocols. Okay, so between nodes, how are they talking to each other? Time check. I'm doing all right. So how are they talking to each other? What is on the wire exactly? Well, first off, everything's encrypted.  You'll see chatter encrypted, small chunks of stuff going over a bunch of protocols. I picked port 5150 as the default if you kind of want to smell around for it, but other ports get used if necessary. So nodes will find each other one way or another. I think if you put it on port 53, you can just use it on the airplane without paying for that. Anyway. Yeah. So the schema language that we're using is a in-schema upgradeable documented RPC called Captain Proto. Captain Proto is written by the same guy who started the protobuf project at Google, but it was meant to fix a lot of the schema upgrade problems and produce a zero copied deserialization system. So we're talking about something that uses the same decrypted on-the-line message format as the same as the in-memory format.  The RPC itself fully supports private routing and we're gonna get to that. And it has schema evolution built in so the next version available doesn't break apps that only use the previous version. And it's cryptography independent. So I'm gonna skip over a couple of slides because there'll be about 15 minutes left, but effectively the RPC operations are a nested set of Captain Proto definitions that define a series of operations like pinging and status finding nodes and then doing things like distributed hash table value gets and value sets. And again, some RPCs are unidirectional, some are bidirectional, they expect a response. Distributed hash tables get a lot of press because they were like the backbone of a lot of the file sharing tools. They're used in things like BitTorrent and the old school Nutella. And if you wanted to download executable files so they weren't P3s. DHT is basically just searched though and the valid DHT is a better DHT because it enforces data locality to the related data. Effectively all the DHTs that you're gonna see out there for like IPFS store little tiny bits of stuff very distributed across the hash space. And what ours does is it actually lets you store a bigger chunk of stuff. We're talking like a megabyte per key across an array of subkeys that can be allocated on a per writer basis. Now what does that mean? Well DHT keys are signed key pairs with a public key. It represents its location in the hash and the private key lets you sign the data that's pushed to the keys value. No other DHTs right now let there be multiple writers to sub chunks of those keys. You can build some pretty powerful distributed synchronization and data structural paradigms there if you can allow people to commingle data on the same hash key. That means that you have a conversation you can put it in line in one place and have a private routed but you can have the data located in the same place. That allows for that sort of caching to happen and for related data to be all together in one place. It means you don't have to search the whole network every time you need to find a new thing. This makes our DHT faster. So one of the reasons that we wanted to do things this way is that we could avoid using blockchain or a coin. To me using a coin is an accessibility issue. It's making sure that people that aren't as comfortable with the internet are not going to be using it. Also, it's putting a price on something that I feel is priceless. You shouldn't have to pay for privacy. It should not be behind a paywall. Privacy should be free, accessible and available to everybody from the start and that is it. One of the things that we really built in with Valid was to make sure that we are building it for the people in this room. We are building it for the people outside of this room. We are building it for the people that are still on Facebook because that is the only app that has made itself accessible to them. We want to build this for the people that don't want to see the privacy, like what goes on behind the curtains. They just want to click and things are growing great and that's what they wanted. They don't want to wait. And the one thing that I really love about what we're doing here is that we're making sure it's seamless. Privacy is there but it's just the baseline and that's how it should be. And we can get into why this is not a free lunch for infinite storage. There is some tricks to it but generally speaking you're gonna be able to use the DHT to store a whole lot of stuff and the network will support you. So talk about private routing. How is this sort of like Tor? How is this protecting people's IP addresses? If I launch my Valid-powered messaging application how is it that it maintains its speed and keeps people's IP addresses private? Okay, I'm gonna define some terms. There's a safety route, a private route and a compiled route. Now this is a little different than Tor. Tor has things like guard nodes and entry and exit nodes if you're familiar with those. Safety route is sort of like a guard node if you're thinking in terms of Tor terminology. So the idea is that if you have two people talking if only one end of the conversation can control the entire route then you've lost. They could pick nodes that are adversarial or phoning home with everything. And that's no good, right? If you wanna truly be able to keep yourself private neither node needs to you should be able to have to trust the construction of the route. So what we do is we build our routes in two chunks. The sender allocates a safety route for sender privacy and the receiver publishes a private route for receiver privacy. Those are compiled together to build the circuit that the communication happens over and the nodes in the middle don't understand necessarily where the end of the route is. So you have to assume that if I look at A, N8 and N7 A is choosing those nodes and N6, N5 and B, B is choosing those nodes. But when they snap together the nodes don't know any different. And you have a circuit that is connected. And we actually used to know to snap them together in this onion style encrypted payload where the addresses and public keys of the next hop are embedded in an onion style peel off a layer as you go system. So this blob of stuff has a private key associated with the route itself, not with the nodes. So everything gets signed but it's associated with the private route or the safety route not with the node ID or an identity. That's allocated on a per route basis and these things are coming and going all the time. This is one of the reasons why we don't necessarily require perfect forward security. We don't need to worry about long encrypted people monitoring a single node for a long time and then going back in time and cracking that conversation. It's because it's moving around all the time. These routes are coming and going. You'd have to monitor the entire valid network to be able to generate enough information to be able to utilize some of those differential crypto attacks. So that envelope that you build has this header and an encrypted chunk of stuff that is guaranteed to be de-aged across just the private route and the safety route and as it goes from node to node we're shrinking those payloads and eventually it drops off where the end can receive the encrypted blob. All of these slides are gonna be available online if you wanna tear apart the exact cryptographic implementation and of course the code's open too if you wanna read it. So toward the future, there are ways to improve private routing. We wanna do per hop payload keying as well. We wanna minimize the number of things that you can glean about traffic from sniffing the wire directly. So reducing the number of things that are common between packets is a good goal over time. Right now we also do some internal hop counting. That was for debug purposes. We can just drop that. We have bidirectional routes today. Allocations are done directionally. We could drop that and just go with bidirectional routes to begin with. We could do things like hop caching and increasing our hop counts if we wanted to. Right now our hop count is effectively equal to Tor's hop count and they did a whole lot of math on why a single guard node and a single exit node would be sufficient. We actually have two extra nodes in there but the reason is why is to make sure that no node can look to the left or to the right and know anything about who they're talking to. As we said in the beginning, we really wanted to make sure that this is private. Make sure that nobody can see your location. It can't get your IP address. You have to invite somebody to be a part of your network. You have to, you know, nothing is going to be forced upon. You are put in an algorithm. So that means that you have a lot more say as a user in how this is being used. The no IP address means no tracking, collection or correlation. That's right, no tracking. As of right now, that is the biggest way. Well, let's give it up for no tracking. How nice is that? Right now that is the biggest way that people are monetizing our internet use.  And instead we have had billionaires that have decided to monetize those connections and seep every little bit of information and data out of each connection and use that they can. And you know what? A lot of people are falling for that. We have made, like I said, privacy has to be accessible for everybody. We have to make sure people understand what that means and we have to make things that are going to entice them, that are going to be inviting to everybody. If we do things like build social media networks like, you know, if we get our parents off Facebook, we're all free, okay? So let's build that. Come build that with us. Let's do a thing. Okay, so how do you do this with us? Valid loves Rust. We are crabs. We have crabs. We want more crabs. Valid is written in Rust. The crates are going to be published. I wrote this before I said that the crates are going to be published. The crates are on the Git lab and we'll explain that a little bit more. We haven't published everything because we're still working on Rust doc because when you're rushing a product out the door, you don't get time for making sure the documentation's right, we're getting there. The crates will be on crates.io in about a month probably as we make sure the docs look as spiffy as they deserve to be. There is a power user quick start. When you are ready to run your own Valid server, you'll be able to do that by either cloning the code and running it, or you can get DEB, APT, or RPM packages from our package servers today. Just download it, install it, turn on automatic or unattended upgrades because we're going to keep changing this thing and keeping everyone up to date will help the network out.  So knock yourself out with that. We also love Flutter. Flutter is a cross-platform mobile first application development framework. Powers all kinds of cool apps like your Instacart and DoorDash and all that kind of stuff. It is Dart internally, which is a JavaScript overlay that does a really good job of providing asynchronous programming to environments that deserve it like the web. So we have a first-class FFI and JavaScript wasm plugin for Dart today. And we have actually written an app using it that we will talk about later, maybe at the party tonight. You know what's going to come to the party? Yeah, I hope so. And we love Python too. If you want to learn how to use Valid and just hack on it and mess with it, we support Python today through a JSON API that's a no-compile way of talking to a Valid server. So app install Valid server, pull down the Valid bindings for Python, and you can start writing little apps and scripts and things that talk over Valid today. Our demo lab tomorrow at 10 is going to talk and demo the Python side of things and show you how you can make your own little chat app that is completely private, distributed, and encrypted both at rest and on the wire. And so how can you help? We need coders and hackers. But more so we need regular people. Everybody. Okay, we need everybody. It takes a team, it takes an entire village to build something that is approachable and usable for everybody.  I love all of you hackers. But we need people. We need human beings. Regular people. We need to speak to human beings. So let's make sure that everybody here has a voice and it all matters. So you can find us online, valid.com is up. We have a Twitter, you've probably seen it ad nauseam for the last six months, but it's there. We're also on Macedon. We love Federation. We want to do more with that. We have a Discord coming up. And we have a GitLab that is going to be open now. So feel free to go poke at it and see what we've built. Also, if you are here looking for a flag for a certain CTF, it is not here. It is in that code. You might have to read the code. It's in there somewhere. So you can see it live. Two night, we have a release party at 8 p.m. We're rocking the house.  It's gonna be a wild time. CDC Highdrinks, you name it. Have you ever heard of a little thing called B.O.2K? Let's bring that back. Let's bring that vibe, that feeling that you can do something that we can just mess the world up. We have the Colts of the Dead cow. Enforce. They're here. Come on. Let's all do a hack to vision together. Awesome. Let's do it. If you have any questions, you can bug us out in the smoking area outside in about 10 minutes. All right, talk to you soon. Thanks, everyone.


All right, welcome to a deep dive.net and the CF pipeline. So, a little bit about us. I'm Larry Smithmire. I've been with Majinik for seven years. Over 20 years in software development. I'm based in New York City. And my co-host. I am Nathan Audenweigner. I've also been with Majinik for about six years. 20 years in the industry here. And I am an accidental resident of Cleveland, Ohio. Okay. So, who is this talk for? What is this talk about? This talk is kind of for a couple of different audiences. And now I see that there are five of you. Hopefully, you'll either be someone that's been doing .NET for a while, or someone that's been doing Cloud Foundry for a while. So, how many people do .NET programming? Okay. About half.  Java, mainly? Okay. Anyone new to Cloud Foundry? New to Cloud Foundry? Okay. And are you using Git? Everybody's using Git. It gets the standard Git flow. How do you do branching? Do you do branching with Git flow or just branch, however? Okay. We'll talk. And then for your pipeline, are you using, anyone using Azure DevOps already? Or do you use Jenkins to do your builds? Jenkins? Okay. So, this is kind of a 100 level talk. So, we're going to keep it light and fluffy at the beginning. And then at the end, we're going to show a demo. And we'll show Azure DevOps all the way through. So, moving on. We're going to start out with the process. We're going to move to decomposition. And then patterns for .NET teams that are working on Cloud Foundry. We've been doing .NET for a while. And, you know, we're kind of coming into Cloud Foundry and with fresh eyes looking at it, saying this is how you can transform a .NET practice into a practice that can work within the Cloud Foundry realm. And, finally, DevOps and how to actually get your code published. Okay? Processes. Thank you. So, we just want to talk a little bit on process. There's a lot of different flavors of Agile. Who here is using like a scrum type model? Kind of sorta, yeah. Anybody using Kanban? Kind of sorta. We've got one. Okay. These are kind of the two general flavors that we see out there. We just wanted to highlight that the pros and cons on either side of these, they do have some differences. So, Kanban, you're trying to maximize flow and minimize like the number of things you have in progress at a time. Versus a scrum model, you've got a nice iteration boundary and you plan the work for the two weeks. The point that we're getting at here though is Kanban seems to work well with teams that have a fair bit of maturity. There's a few less guardrails in place so you can move a little faster. But the fewer guardrails kind of means that it works better when you've got a mature team. The thing that I think that scrum helps with is if you've got a lot of chaos up above the team with the requirements, scrum has some ceremonies and processes that protects the team from too much churn. You commit to two weeks of work, you know what you're doing, you finish it up and move on while the business is figuring out what's next. So these are the two flavors. Use what makes the mess sense based on context. Decomposition. So this is a mess. This is where you maybe are right now. If you're doing software in the traditional way and you look at what you have, you do a survey of the software that you have in place and you're wondering, how do I break this down into microservices? It's like bowling the ocean, right? Eating the elephant. You've got to start out, do it one bite at a time. And the way you do that is by decomposing your problem. And how many people have done or heard of event storming? Is event storming in your vocabulary? No. Okay. Event storming is a workshop method that helps you define the actual business problems. And it's a good method that maps very well to microservices. So you bring all of the people into the room that are involved in the business. And you're not solving a technical problem, you're solving a business problem. At this level. Okay. So you take all of the technology out of the room. Event storming, you're using sticky notes and butcher's paper, right? The big long sheets. And what you do is you set down with all of the people that are involved in the business and you start defining what the business actually does. And you work from the beginning to the end. And you use sticky notes, orange notes for events, blue for commands, yellow for aggregates, and purple for trouble spots. Okay. And look up event storming. There's a great talk. There's a lot of great talks about how to actually do it. So Alberto Brandolini has a talk called 500 orange stickies later. Or 5,000, 50,000 orange stickies later. And he's the person that kind of came up with this and has put some structure around it. He's got a book that he's not finished writing yet, but eventually we'll be finished writing on this. And it's great. So let's look quickly at decomposing with event storm. We start out, we put down these commands, these things that are happening like pay a bill. Then we layer in these events that are happening like our shipment is delivered. You know, we want to receive a shipment. So the shipments delivered. These are actions. Then we come back and we add in problem spots, things that we need, where we need to do checks. Okay. So we're just breaking a problem down into smaller pieces, decomposing it. Once we've done that, we break them down into kind of flows. We put these lines in place. Now we're going to pick one. We're going to say that we're having the most problem or our business can be best served by us automating this shipment receiving. Okay. So the idea with event storming is that you're going to break out all of the problems and you're going to focus on the one that gives you the most business value with the least risk. Okay. So that big mess of problems up there, you don't want to do all of them. You can't do all of them at once. Pick the one that's going to give you the most bang for the buck. Okay. So for us, we're Microsoft's focus, right? So once we've decomposed it, we're going to drop our stories. I mean, excuse me, we're going to drop our cards over. We're going to put them in as stories into Azure. The keys for decomposing don't decompose things too small. Don't leave them too big and really rely on the event storming to outline the functionality that you need. Okay. You're not solving technical problems with the event storming. You're identifying business needs. Okay. Next source code. All right. We touched on this a little bit. It sounds like most everybody in the room here is using Git. That's kind of the message here is it seems to be the industry trend. Beyond that, what we want to talk a little bit about is the branching model because that impacts your pipeline quite a bit. The patterns that we see being preferred here is a trunk based development model, right? So typically you have a develop branch and everybody's bringing their code back into develop regularly, right? A couple of days for a branch maybe. But short lifetimes. So you want everything in a single branch. And then you want a stable master. So stable master says you've got a branch that represents what's in prod. And at any point you could build whatever's in that branch and that's your production, right? It's all good builds. Gitflow is a model. It's not the only one, but it's a model that's out there. From what I've seen, it really does a great job of doing these three goals here. It's well proven, well practiced. There's tooling out there, but you don't have to use it. And I will suggest here that the Atlassian documentation on this. They've got a really great walkthrough that goes through how Gitflow operates. Really great diagrams. Lots and lots of information here. But Gitflow looks like a mess. If you look at some of the diagrams, right? It's branches and everything everywhere. This kind of takes it piecemeal and says, okay, what's the point of why we're doing these different branches? What types of branches do we have? Feature branches, release branches, bug fix branches, right? And there's patterns that they recommend for how you do this, okay? So good resources there, but main message, Git and Gitflow. Okay, I'm back. Enablement. So enablement talks about how we, how those of us that are here, the smart people in the room, the people that are our leaders enable our teams to work well together. And so you're not an army of one. You're not going to do this by yourself. You're not going to be able to transform a business as a singleton. The whole is greater than the sum of the parts, right? We need our teams to work together. And the way that we do that is we enable them, we give them the tools that they need. And one of the ways that we do that is we, and I'm going to say extreme programming and it makes me cringe when I say it, okay? When you get two people on a computer together though, there's a synergy that happens. It's not just one brain working anymore. It's one brain that's typing and actually implementing the code. The other brain can be used to solve the problem. And that cognitive overhead, right? The amount that you have to keep in your brain when you've got a partner sitting beside you goes down. And it frees you to work on the piece of the problem that you're working on and let them worry about the other part. Now, Nathan and I are working from different cities. How do we handle that? Well, Visual Studio Code and Visual Studio itself has a shared programming model so that we can do live sharing and we can both be working within the same environment at the same time. It's really cool. Been out since 2017. Nobody's really using it. Okay? They just released a new version of it last, or actually yesterday. Yesterday was the Visual Studio launch. They've doubled down on it and now they're making it even easier to have multiple people working within the same environment. So we're sharing code. We're not on the same desktop, but we're within the same code environment. So Visual Studio Live. So we also talk about building, kind of building ramps for people that need to be onboarded. And we do that through things like test driven design. Okay? And I'm going to bring testing in as an on-ramp because if you're new to a project, what's the first thing that you do? Well, the first thing that I do is I look for tests because tests should show me how the programs work. I should be able to follow through the tests and see what this program was intended to do. I can also run them and make sure that the program works on my machine and works in my environment. So we also plan feedback loops. And this, again, is a way that we... So I develop code, and even if Nathan and I are not paired, when I develop code, I send it to Nathan for a review. And he reviews my code. While he's reviewing my code, I'm reviewing his code. So we start out our morning, and I start with the controllers. And I'm going to spend probably until 2 o'clock, 2 in the afternoon, working on code. Then around 2, I'll ship my code over to Nathan. He ships his code over to me. And we spend the last bit of the day coming up to speed with what the other person's done. So this is a code review, looking... Not for flaws, but looking for ways that we can enhance and ways that we can extend the model. We also build enablement cookbooks. So write down the steps that you need to do so that you can hand it to someone like a new developer that doesn't have a background in it so they can do it without having to bother you. It's self-preservation. I don't want someone to have to keep coming to me every time they need to know how to do something. So I put it out in documentation. Personally, I like to do videos. I like to just do a screen capture. Someone asked me a question. I say, great. Let me answer that for you on Skype. And I'm going to record it. And I'm going to put it on a share. So the next person that needs that question answered, they can find it without even bothering me. If they do ask, then I can send them the link. Answer questions one time. None of this is .NET related. We're not to .NET yet. But it's the process that we've been using in .NET that we're bringing to Cloud Foundry. Hopefully some of this sticks and helps. Cookbooks, tools. There's a lot of tools around building out cookbooks. Hugo is really easy to build a static site. So just some things that you can use. Conclusions. There have been studies where a senior developer spending five minutes with a junior developer in the morning can improve their productivity by 50%. You just need, if you're the senior leader, you need to talk to your people in the morning. For us, we use Scrum and Kanban. We have standups. Spend the time, spend the five minutes to talk and find out what they're doing and point them in the right direction. Make sure that they're arrow focused on what their tasks are for that day. Spend some time pairing with them. If they're having problems, don't just, you know, spend the time to teach them how to fish, if you will. Don't feed them. Teach them how to fish. Teach them how to learn what they need to do. Cookbooks. Capture your key things. Cookbooks don't have to be text. They can be videos. And formalize and clarify. That's it. DevOps. Yes, we are. Take your time. All right. So this is hopefully or maybe what you guys were coming to see. We're going to talk a little bit more about the actual pipeline. We're almost going to be using Azure DevOps, formerly known as Visual Studio Team Services. I'll ask again, who has used it or currently using? Okay, a couple of people. The patterns we're talking about here could be done anywhere for those using Jenkins or whatever. A lot of these hopefully can be used in different tooling. We're just using Azure DevOps because it's Microsoft land, right? Familiar to many people. Before we start showing you Azure DevOps, we just want to talk a little bit about a couple of aspects here. So .NET Core. Who else is using .NET Core so far? Anybody on .NET Core? We got one. Full framework. Anybody still on full framework? Okay. The message here with .NET Core is it is a brand new world with .NET Core. It's been rewritten. There's a lot of performance enhancements. I'm on a project right now. We took the same bits, right? We're targeting .NET standard. We put the same bits and ran them in the full framework runtime. Then we ran them again in the .NET Core runtime. The performance was like a magnitude better under .NET Core because of all the work. They focused a lot on allocations. They focused a lot on memory footprint. Tons of performance gains there. The threading model is different. Many, many improvements. Take a look at it. The other thing that .NET Core brings obviously is now that you can run your .NET apps on Linux. That opens up a whole new world of options. Containers are one of the primary things .NET Core was targeting when they built it. A great option here. It's also a great option in Cloud Foundry. The build pack for .NET Core is targeted specifically for that and works really, really well. Testing. We've talked about this a little bit already. I'm going to assume everybody here is doing testing. Unit tests are table stakes. What I do want to recommend though is make sure that you're getting enough integration tests. Again, the current project I'm on, they have a bar that says we've got to have 90% code coverage. We get that bar met, but I've still seen too many times where we've got good coverage, the tests all pass, and then we run the app and it doesn't work. The individual units need to be proven that they work together. What we're looking in these pipelines for is both unit tests and integration tests, both automated. For environments, again, I'm going to assume everybody has multiple environments. You've got local dev QA prod. We want to separate these out. The goal that we're looking for here is that your environments should be temporary. Treat them as infrastructure as code where you build them up using code. That means you can tear them down, repave them, make sure that they're clean. That's one of the things I want to show you in our demo here today. Cloud Foundry makes this super nice, really easy. Then what we're looking at getting to is two main things that we're going to build. We're going to build a CI pipeline that's going to build our code, run our tests, and then we're going to do a continuous delivery release pipeline to get our bits onto servers. In the continuous delivery pipeline, as I mentioned, we want to do infrastructure as code, so we're going to build our space. Or you could build out it for an org or whatever else, right? But you build it as part of the pipeline. I don't have it modeled here, but you need to factor in things like your database migrations. There's a couple of different options. I'd be happy to talk to people about some of the things I've seen, but you want even your database migrations to be scripted. One last point that one of the guys at Majanic has really tried to pound into our minds is this idea of you build once and deploy that many times. I've been on a number of projects that don't follow this pattern, right? They have a separate compilation and build and deployment for each different environment. The message here is you build the bits one time, and you take those bits and you put them in each of the different environments. Again, Cloud Foundry in 12 Factor makes this really nice and really easy. We leverage the environment variables to configure the app for the environment we're in. And lastly, local environment. I'm going to show a little bit of this here, too. I think local environments are becoming increasingly tricky. It used to be you'd have a couple apps, right? A couple services, big monoliths.  Most of it's there. You might have some setup. One of the projects I'm on right now, we're going to be running like 30 different services. It's really hard to do 30 different individual setups. So what we're leveraging in that project is we're using Docker images for running the bits. We're using Docker compose locally so that we can script basically launching and loading all those things and connecting them. And then what I'm going to show today is, for example, using Docker images to run the spring containers that Cloud Foundry might offer, specifically a config server, right? So think about your local developer experience as you think about the pipelines that you've got that are going into the Cloud Foundry instance as well. So let's jump into Azure DevOps. I have a bunch of slides here. I'm going to go through them quickly. And then we're going to go and see this for real. But the slides help me make sure I don't miss something in stepping through how we set this up. The point here is we've got Git repo. We're using a Git flow structure, master develop and feature branches for the code. Then we've set up, and I used the Azure DevOps classic template here. They have a newer template or a newer approach where they want you to use YAML to build all the stuff. But this is much easier. So this does the standard steps, right? .NET restore, build, test, and publish. I get some bits out the other side. And the last step here is to publish the artifacts. So within Azure DevOps, that means I'm going to take these DLLs and all the output files, and DevOps is going to keep that in a little bucket that then I can reference later on when I do a release. The one note here is that by default, it's going to say, hey, do you want to zip the output? We opted not to zip the output. That makes it easier to kind of deal with the individual files that we need. The other thing we did on this guy is just check the box, right? Yes, we want continuous integration. We are doing that at this point on the develop branch. We don't want to build anything and everything. So this one is targeted just at the develop branch. But you can customize this to your needs, obviously. Our goal as we talked about is we want to have multiple environments. The model that I'm showing you here is one space in a given org for each of those. Dev QA test. And we're going to set up a release pipeline. So what I showed you before was the CI build pipeline. This is now the next step. We're going to set up the release bits. What this kind of shows as an overview is on the left, you've got the build output. And in this case, I manually triggered it, but you can set it up for CI triggering. And then this is going to go from the bits out to the develop space. If that's happy, we can manually approve it to go to the QA space. And if we're happy there, then we can manually approve it to go to the production. This is admittedly simple. And in a very real pipeline, you probably would have some additional stages in here where you do some integration testing, have your QA builds run, etc. Make sure that everything's happy. This is a simplified version so we can see the points. This is what an approval looks like. You can see that it's happy in QA. Do we want to go to prod? You just say, yep. All right. This shows what the release pipeline looks like after it's run. And you can see here that it's gone to Dev. It's gone to QA. Let me see if I can see here. So these are the different stages that have run. And you can see that it's sitting here waiting for prod. One of the things that I want to highlight here, though, is I find Azure DevOps naming a little weird. They have, to get your code out, you create releases, and they have release releases and release pipelines and stages and all these things. It's kind of confusing to me. What we're looking at at the big thing is the pipeline. So we create a release pipeline. Pipelines have stages. Stages have a bunch of tasks or steps in them. But then once you've got that built, it's kind of like the template that you start with. And this is the part that's confusing to me, is that then you create a release. And a release is kind of like take these specific bits and move them to these specific environments. And you can customize that. I just find that naming a little hard to deal with. All right, so here's the stages and tasks. This is specifically the dev stage with a sequence of tasks. Hopefully this is looking somewhat familiar, right? The CF push is kind of ubiquitous here, and that's in the push to cloud foundry. But we initialize, we download our bits, we get the CF client, and I'll show you that in a minute. Infrastructure as code, we create the space, we push the bits, then we programmatically create the services, bind the services, and start the app. We mentioned that we push the same bits into each environment. So what we have here is just showing you that we've got different groups of variables, and you can tie these up so that you have different values for each environment. And then we bind these groups over to a stage, right? So I can set up new environments really easy. I just set up a new set of values here, map them, put the stage in, good to go. This is what it looks like to edit a release pipeline. You can click on a bunch of these things, right? The little person icon is how you do a manual approval. The trigger, you can go in and change things. So what we show here then is for dev, we're looking at the trigger. And this is saying basically automatically kick off, like create a new release and kick it off anytime there's a release available from the develop branch. But for QA, we don't want quite the same criteria. So the trigger here is I want this to run after the dev stage has completed. And we've set this one up with a manual approval too. So it's not just going to automatically run, okay? So here we're going to take a quick step through how we set up these individual steps or tasks. These are mostly bash scripts, which means it's standard command line stuff. Hopefully things you're familiar with doing. This first step, like I mentioned, is we have to get the CF client. I'm using just a plain vanilla Azure hosted Ubuntu image. It does not yet have Cloud Foundry on it. What we're doing here is just a curl command, pull it off GitHub, extract it, and put it in the right directory. Once we've got that down, now we can go ahead and connect in to create our space. A couple of notables here. I built this thing originally with the CF login command. And there were some times that it basically just like hung the whole flow, didn't progress. And what I found is that the CF login, it's sort of an interactive thing. It'll prompt you waiting for your password. That doesn't work so well here, right? So what I found, they have an alternative set of commands. So CF API says, here's the API. CF auth says, here's my username and password. And those are not interactive. They pass or fail. So that works better in this scripted environment. Next we go and we create the space. I know this is hard to see, but we're pulling in some environment variables. So this script is the same for each of the environments. It's just the variables that change it. Once we've got the space, then we target. CF target. Here you can see on the left is the name of the variable from our variable group. And then you can see that we're pulling that in to the bash script and making it available as a bash environment variable. Next, what we did is we used an extension that's in the DevOps marketplace. This is a push to cloud foundry extension. It makes it really nice to push a code because it's got a bunch of different boxes here you can see where you can use environment variables really easily. There's some features in here that we didn't leverage. I'll explain that in a minute. But basically we created a cloud foundry connection. That's that second box down. That's just the URL, username, password. Then we're connected. And for the rest of them, we're using mostly the variables from the variable group. Name of our app, the memory, the domain, right? So these are pulling from variable groups. The one note is, by default, it's going to want to start your app after the push, but we actually don't want it to start yet. If we have a clean space, I don't have my services there yet. And if I start it without services, it's not happy. The point here on this one is just the working directories. I had to fiddle with these a little bit to make sure that it knew where the CF command line was and where the bits were from my release. So after we push, then we create services. Again, standard CF command line stuff. We're creating a MySQL DB and a config server here. The other note is that create services is an asynchronous command. So you say, create them, and the command line comes back and says, good, but they're not there yet. So there's a couple of strategies. This one takes a really simple strategy and just sleeps for 10 seconds. But there are some scripts out there where you can query Cloud Foundry and say, hey, is my service there? And that'll give you a little bit of a pause in your pipeline before it goes to the next step. So the next step is bind. This is the part that'll blow up if your service isn't ready yet. So that's why you want that pause. But we're binding these two over to the app. And lastly, then, we call start. And this is the one that can take a little bit of time because it's running all this stuff and getting things running. But we've automated it end to end at this point and got our service deployed and out there. I found these two variables interesting. The CF command line has these two variables that can kind of control your time out for the staging and the startup process. So if you want to put some controls around that, these are helpful in that space. And now we get to go to a demo. As he's setting up the demo, one thing that I do want to mention is we broke kind of the rules and we have a manual step, right? We have a manual to go to QA. That's actually something that we've learned over time. QA, our QA really doesn't like it when they don't know what they're QA-ing. So what we did was we said it's manual. You decide when you want to get new bits out of QA. It's all yours. We're not going to push anything to QA. We're going to put it up there. It's always going to be staged. We're always putting code in dev that's QA-able. So push it. Take it off when you want it. Same thing with prod. We have our business users that actually get a kick out of being able to push the button to move code because we're letting them decide once UAT and everything has been done when they're happy with the code. Okay? Not us. Demo time. Demo time. We'll pray things go well here. What we've got is a sample that Magenek put together. It's basically a simple API that kind of imagines a bike shop. The source code for all this is linked in the slides. The slides are up on sked.com. So you guys are free to pull them down and free to go take a look at the code. I don't want to dive deep in the code because that's not really the point here. But the sample does use SteelTow. It's got some actuators in there, some health endpoints, et cetera. So it's a decent and nice sample to look at for a .NET Core application. What we want to do here, though, is take you through a demo of we've got the code, it's already running, and we want to exercise this pipeline. So Larry and I are going to pretend that we're going to pair on a change, get that change, push a PR, merge the PR, watch the pipelines run, and cross our fingers. Right? So here's the API. This is our current bicycle endpoint. Get us all the bicycles. API has a set of built-in, like get, put, post, delete, right? Standard stuff. What we don't yet have is... Well, we'll get to that in a minute. Larry's going to tell us what feature we should do. So are we ready? So I see a lot of bicycles here, but my budget is not the same as yours, I guess. I don't need to see a $4,000 bicycle. Is there a way that we can maybe limit and give me a way to query on price? So I'm going to put a user story in called Browse Inventory, and on that user story we're going to say, we want to be able to browse it based on price. We'll put acceptance criteria in there, we'll do all of that within the regular .NET tool. Nathan has taken it, he's activated it. Sounds good. Sounds good. So let's jump to our code base here, and we want to implement a price filter. So through the magic of git branching, we have just implemented a new feature. We can now filter by minmax price. So what I want to show you here is just a little bit of the code changes. Again, this is not really the point, but on the query string now we can pass in minmax. When we do that, this will optionally go down and use a search query. So that's in our bike repository here. So search bicycles now supports a query, minmax. The other thing that we've done in following our own advice here is we've made sure that we have unit testing. So here we're just mocking out some things and we've got our test. So before we push, let's go over here, we'll make sure all of our tests run. I know that's really small, sorry. So that window won't grow. Likewise, so command line for those who prefer that, let's see where we're at. So we're on our new branch. So command line.net core loves command line. You can do so much from the command line. You do not need Visual Studio. I love Visual Studio for .net core, but you don't strictly need it. So we can do .net build, tappy.net test, two passed, no failures. Good to go. What's our coverage number on that? That test sounds awful. I think we need to... I think we have some work to do. We've got some work to do on that. One thing that we don't have in our pipeline is we don't have any filters you can actually put in place that you will not advance, not allow code to be checked in unless you meet a certain level with your code coverage. We don't actually like to set levels. What we want to do is though, we set a band, and if your code coverage drops more than 5%, then we know that you've added a lot of code without adding any tests to back it up. And that's when we stop the branch. We don't say that you, within our project, within the project I'm in, we don't set a level. We say test what you need to test, but always test the new code. So I just pushed this branch. I want to jump back because we moved a little past a couple of things I want to show. I've already got this deployed up to PWS in one of the environments. So let's just take a quick look at what we've got over there. The URL that I was showing you here, this is the cloud deployed instance. So this is our API over there. If we look at our environment, so again, we're using PWS here, so I've got a nice app manager experience. Can do the same with the command line here. But in my dev environment, I've got the app running. You can see the endpoint. If we go explore this guy, we've got it started. I've got two services. Here's my services. We use a config server, and we're also using MySQL databases. If we look at a couple of the steal-toe nice things here, we've got the built-in integration to see the mappings. So this will pop up all the nice routes that are in my app. It's a nice feature. And we can click right into the app like what we've already done. So let's continue on here. We push the branch. Let's go take a look at our code. Okay. So it says, hey, I noticed you pushed this branch. You want to create a pull request? Sure. Let's do that. Okay. Add the work item. Yep. There it is. Story 8. So we'll create our PR, and Larry's going to scrutinize this code intently. Do you have a touch screen? Yes. Okay. There we go. Approve. Thanks. Excellent. I don't have a touch screen. I do. I got a bad laptop. So we will complete this guy. All right. Let's jump quick over to our build pipeline. And what we can see here is we've got a build already kicked off. Let's go ahead and look at this guy. So one of the nice things about Azure DevOps is it does give you pretty nice build output and logging.  I find this pretty nice. But you can see we're just doing standard .NET build type operations. Restore the packages, .NET build, .NET test, .NET publish. And we're using a standard agent. It's just hosted Ubuntu. You can actually, if you need, if you're not decor yet, and you need to have a special environment to do your build, you can set up a virtual machine and have your own build agent and do your .NET framework stuff on it. Hopefully, you'll get to the point that you can just use the Ubuntu, but crawl, walk, run. Take your steps. So this can take just a minute. I'm going to jump over to... We'll take a look at a prior build. Let's look at this one. So here's the build output from something that ran. The output that we'll see should look like this. If we jump into any of these, you can see the output, all the restore. And we can see... Hopefully this is big enough. Here we're doing our build, test, and then the publish. Publish just takes the bits and put them in a directory that then we can publish the artifacts. So we just tell the build where to pull those and how to store them. So 199 files. Okay, and then we're done. I can see if this guy finished running tests. And what we're going to expect to happen next is that this is going to create a new published artifact. The release is triggered on those, and this is coming from the develop branch. So the release is going to say, great, I'm going to kick off a new release automatically. So let's go look over there. That's right here. And we can see that release 21 was just created, 1447. So we'll take a look at this guy. And we can see a couple things. So here's our continuous deployment trigger. You can see which artifacts it triggered on. And now it's running this stage. Let's go ahead and look at the log output of this guy. So initialize job, download the client, create the space. A lot of stuff is going pretty quick because the space already exists. Push the bits. Create the services. Note here that this is saying, hey, that already exists, right? Which is kind of nice. The command doesn't blow up just because it's already there. Bind and start. So this is your standard output from a standard CF push. So while that's running, we'll just kick over here. So CF target says we're pointing at the dev space. Let's look at our apps. We can see that we've got this bike shop API. Right now it claims it started, but it ought to say crashed or restarting. So down, waiting for this guy to come back up. While we're waiting for that, what I want to show real quick, I mentioned that we have this running locally as well. So if I do Docker PS, I've got documentation on this container and what we did here. But this is a Spring Cloud config server container out there. This is one of the Spring services that I needed. So I found this container to be the best. This is running in Docker. If I take my application here, now that I've got all these changes. So let's just do a local F5, launch my app. So this is going to spin up in a self-hosted Kestrel container, not container, self-hosted Kestrel serving process. And now I've got my app running locally. Additionally, people familiar with Swagger, OpenAPI specs for APIs. I see a couple hands. So Swagger is a standard out there that lets you document the Rust interface on your API. On top of that spec, then you can build this nice UI. That's what we're seeing here. The Swagger UI has some nice built-in stuff, so I can try out these endpoints. And notice now that we have these API query string parameters, so I can do min max price. So let's do this without any and see what we get. So locally, without any filters, I get all three. I know there's three in the database. But if we say that Larry doesn't want to spend more than a thousand, then we should see a few less come back. There we go. A Schwinn and a Nishiki. So a couple points here. One is we're running local. We're using a Docker container to mimic some of the services that we need. We added the feature. It shows up here. We can test it locally. So let's go ahead and kill this. Control C, that goes away. And let's go back to this guy. Nope, wrong one. All right. So now our app's up and running. We can see that over here as well. Let's take a peek here. Yep, apps up and running. Just started. Let's kick over here. So this is the same endpoint, but we just refreshed it. So hit a five. Yep, still works. Let's do a min price of 500. And now we get two. So API is working. I will tempt fate and see if the swagger endpoint is working out here. It is not. There's some sort of bug that we're running into. I think it's a SSL TLS thing. Sometimes the swagger UI works in CF and sometimes doesn't, but we did not figure out how to get it working in time for the demo. Let's go back to our release here and we can see this is our guy, right? 21. Yes. Cool. So start service. This is what we were waiting for. Finally got through and now we're running. Okay. If we go back up here, we can see now we're sitting here succeeded and we're just waiting for QA. Okay. Cool. So that I think covers it. That's the demo. Yep. We've got another slide or two that say reiterate, but are there any questions? Yes. So all of the, so the question is, is everything that we're, that we're showing here running under Azure DevOps? And yes it is. Everything here is, is native Azure. The Azure pipeline actually is split out now. You don't have to go through the Azure DevOps. You can use the Azure pipeline by itself in your own environment. They did that recently. Just look up Azure pipeline. They'll talk you through that. Yes. Yes. So good question. The question is because we have the services scripted, because we have service creation scripted, what happens when we rerun it? Nathan, can you show the, on the dev, there's a task. It just says it's already there, no problem. Yep. And we can show it in the logs. Yep. Let me go, so we sort of saw that a little bit in the logs here for this guy. If we look at the create space, it's basically just going to say, hey thanks, this already exists. I will note that I had to, I had to toggle a couple of things. There's a setting on the batch scripting commands that says, do you want to fail the step if there's anything written to standard error? And some of the CF commands will dump something to standard error, so I had to turn it off for that. And other ones don't, but generally speaking, the CF commands are able to rerun and they don't complain. Cool. Any other questions? Yes, sir. The same, the question is, does this, is this just for CF or could it work with Kubernetes or Docker or any other container system? It can work with anything. The work that Nathan did to put these in was really just embedding the command line, the batch script in the pipeline, and anything that you can embed in a pipeline, you can embed in this. Sure. Are you asking if, like, the demo that we're showing here would work for Kubernetes or just Azure DevOps in general? Okay, yeah, the demo is just Cloud Foundry. Yep. Well, but we wouldn't, the code wouldn't have to change. Okay, anyway, sorry. Yeah. Yep. Any other questions? All right, let's go back to our slides here. Okay. Summary key takeaways. Watch out for lack of consensus. Make sure that you have cookbooks, but that your cookbooks are loose. You know, don't get, don't have your cookbooks be telling how to fillet a specific fish. You want to talk about fish in general. You can get started now. You don't have to have Cloud Foundry in place to do any of this. Relay on your event storming for decomposition. If you take one thing away, please look up event storming and look at the way that that helps you break your problem down, because what it does is it allows you to get everyone in the room. You bring your business in as well, and you're actually solving the business problems, not the technical problems. And if you bring everyone in, you start having, well, this is what I do. You have the people that are actually doing the work. And they put their steps down and they say, this is what I do. And their boss says, well, I thought you were doing this and this. And, you know, you get all of that laid out.  You look at where you can actually make an impact. So event storming. Automate your build release pipelines. That's a no-brainer. And script your infrastructure. So have it so that it builds your spaces. So that you have cattle, not pets. Do away with anything that is specific to an environment. Okay. Resources. The slides are up, skedge.com. Nathan and I, we're available. If you've got questions later, hit us up. That's it. Thanks.


Please note that this video has sexual health content Let's look at the different parts of the male reproductive system and see how it works So let's start with the parts that we can visibly see in our body. So one of the part is this Skin pouch of skin that hangs from our lower abdomen. We call this the scrotum scrotum Like I said, it's a pouch of skin hanging from the lower bottom. So it must be Protecting something inside of it, right? What is it protecting?  What is inside of it? Well, the scrotum protects an important organ called the testes So this is the testes You can also call it testicle And we have two of them so the pleura would be testes with an E T-S-T-E-S would be the pleura testes testes would be the singular and So what does testes do? Well the primary job of testes is to make sperm cells And that's why we call it the gonad gonads are the one that ones that create gametes So in males the gametes are called sperms. So testes the gonad which creates sperms creates sperms Now you might also remember that testes secretes a very important sex hormone called the testosterone During our puberty it is because of testosterone that we see Physical changes during puberty in males like your beard grows and your voice becomes very Your voice cracks and gets a little deeper and we also see behavioral changes like we start to get more aggressive All of that happens due to testosterone That's one of the things causes sexual maturity in males But another thing that testosterone don't testosterone does is that again? It regulates the creation of the sperms inside the testes and a curious question could be why is the scrotum hanging down? Carrying the test is almost outside of our body. Well, there is a reason for that You see it turns out that the creation of the sperms requires a little cooler temperature than our body about two degrees Celsius cooler So this requires cool temperatures all right and It's for that reason the scrotum hangs below the lower abdomen So it so the testes can be out slightly outside of our main body and because of that its temperature will be lower So the scrotum protects the testes and it also helps a regulated temperature It also helps keep it cool by hanging below the abdomen All right, once these sperms are created they move towards another organ called Another organ on top of the testes. This is called the epi Di D Musse Little hard to spell and pronounce over there But anyways once the sperm reach over there they start growing and maturing over there Just like how our bodies grow and mature the sperms also need to grow and mature It's inside this organ that they grow and mature. So let me write that over here the sperms grow and mature so mature Sperms are sitting over there Sperms sit over there Now you don't have to remember this name So I'm just gonna put a strike on this for our syllabus. We don't need to remember the name But the mature sperms are sitting over there All right. Now what happens to these firms now?  Well as the penis gets stimulated like we said the sperms are gonna get propelled from the epididymus into yet another organ a Tube-like structure called the vast difference So let me write that So it gets propelled the sperms the mature sperms goes into another tube called the vast Deference and where does the sperms go after that? Well, the vast difference takes the sperms and empties it into yet another duct as you can see over here And then finally the sperms will enter into the urethra The same pipe through which the urine moves out the same urethra and then eventually the sperms can come out of the penis Now you might have a small curious question. Why does the vast difference? Empty the sperm into this duct and then it goes into the urethra. Why not directly into the urethra? I'll answer that in a second But here's one question for us now the sperms once they exit the male body They have to survive for quite a long time in the female reproductive system They require energy because they need to move then acquire nutrition and they also need some help in moving So if the sperms directly come out most of these things cannot happen The sperms may not be able to survive So to help the sperm survive outside our body to give it nutrition to give it energy Along with the sperms some extra secretions are needed and that those secretions are done by accessory glands I'll tell the names of these glands in a second But it's these glands that secrete some fluids into this Particular duct and also into the urethra which mix with the sperm and Provides the sperm with all the nutrition and the energy and gives it motility helps in in moving And so these are what we call the sec the accessory glands which produce that secretion and finally the mixture the sperm in this Sperm and the the fluid mixture which eventually comes out of the urethra. So let's say this is that mixture This now is what we call the semen This is what we call the semen so the semen contains the sperms and It contains all the secretions plus the secretions from the accessory glands All right, let's name the glands turns out that most of the secretions of the semen is done by this particular gland Which is behind the bladder and so it's this is called the seminal vesicle Seminal vesicle and The gland below over here also helps in the secretions and this is called the prostate gland again You may have heard of this gland Prostate and now this answers why we have this tiny little duct over here So the vast difference empties the sperms into the duct these glands empty their secretions into the duct And this is where most of the semen is formed and this tiny bulb like structure is the third gland which also adds its secretion to the semen and Since it's the bulb like structure. It's connected to urethra. It's called the bulbo urethra gland But I'm not gonna write that because we again don't need to remember that It also has another important job before the semen reaches over here It sends out a secretion which is a little alkaline Which cleans up this passage if there is any urine over there because urine is acidic Right and if the semen reaches over there where the urine is present the urine the acidic urine might kill the sperms And that's bad.  That's because the conditions in the female reproductive parts are very harsh And so most of these sperms die the unhealthy ones the ones which are not fit to survive They just die out this is to ensure that only the healthiest of the healthiest of the healthiest sperm can survive and Go and fertilize with the egg and finally if you're thinking about what the sperm looks like here is Schematic of the sperm the sperm is a cell you can see the head which contains the nucleus which has the genetic material Basically is this genetic material, which is supposed to go into the egg after fertilization It has a tail which helps it swim it helps it move we can say inside the vagina and inside the uterus And and it requires energy for that and it's for that reason the body of the sperm contains mitochondria you might know mitochondria is the powerhouse So this is basically what a sperm a human sperm looks like All right, that's pretty much it. Let's quickly go ahead and summarize what we learned So the test is is the male gonad which is responsible for creating the sperms It is protected by the scrotum, which is the pouch of skin which hangs below the abdomen This also ensures the low temperature needed for the test is to create the sperms the young sperms now move to the epidermis That's where they will mature and sit for a while And then if the penis gets stimulated these sperms will get propelled into the vast difference The vast difference empties the sperms into this tiny little duct and these Accessory glands also add in their secretions basically the seminal vesicle and the prostate gland mainly And these secretions help the sperm get their nutrients get their energy and help them in motility And now this forms the semen the semen eventually comes out of the urethra from the erect penis And gets thrown out with a great speed And these sperm contains a head which has the genetic material It has a body which has the mitochondria and it has a tail which helps it move


Gihelaunus was a bird species that lived during the early Cretaceous period. It had a diet consisting of both fruits and leaves, which suggests that it was an arboreal herbivore. This transition in the early evolution of birds is significant because it shows that birds were able to occupy an arboreal herbivore niche, which they still do today. Additionally, this discovery provides evidence of the early evolutionary connection between birds and angiosperms. This article was authored by Yang Wu, Yong Ji, Han Hu, and others.


The alarm slash alert for Roblox incidents and cataclysms, Alaric, was an automated emergency response system meant to minimize the damage of major hackings and anomalous events to its users' games and accounts. Developed in late 2012, it was conceived as a way to mitigate the damage of future attacks, similar to the April Fools incident to Roblox users. Roblox would automatically respond to events in varying ways depending on the situation or class of event it encountered, making it a formidable security system. After the April Fools 2012 incident, a wave of mass panic hit the Roblox community, impacting everyone from clan owners and developers. Items were changed, accounts were unbanned, and insanity reigned across the site on that day in Spring 2012. It seemed nowhere was safe, and if Roblox could get hacked once, what could stop someone like 1x1x1x1 from causing mass chaos in the future? In most players' minds, there was no answer to this question. There were not many safeguards people could use, two-step verification and account pins were not yet implemented, and filtering enabled wasn't heard of. So, what could the users of Roblox do? It was around this time that an anonymous group of developers began work on a counter-exploit system, meant to warn and or prevent these events from happening. The system would use multiple mines of countermeasures to destroy enemy exploits and attacks, as well as an inbuilt notifications system for real-time attack and emergency notices. This system, soon known as Aleric, would be released to the public during late 2012, with a price of about 250,000 tickets. Several large groups and clans would buy the system, them being basically the only ones that could afford it, seeing deployment in multiple group games and bases. Aleric would repulse several events, using its event classification system to determine the seriousness of the threats, and going into 2013, the system was extremely prevalent within the infrastructure of about any major clan. Despite this, public knowledge of the system was practically nonexistent. The system was extremely powerful, and if it fell into public hands, major disaster could occur on the Roblox website. For obvious reasons, no owner of the system wanted this to happen, and so knowledge of it was kept without most secrecy. In July of 2013, an exploiter accidentally triggered a portion of Aleric's emergency broadcast system, resulting in limited broadcasts of AZ-class event alerts message. After inquiring on the forums, the discussion seemingly ended. After this date, it seems as if no new user sightings have been leaked outside of private discussion, seemingly due to larger efforts to conceal the program in response to the aforementioned incident. As of 2023, all current operators and users of the Aleric system are unknown. Although information is scarce and somewhat dubious, it is believed that the Aleric system was the most powerful exploit-slash-tool of Roblox's history, having the ability to defend games from exploits with a large amount of unique techniques. Aleric may use undiscovered vulnerabilities within the Roblox software in order to execute its duties, including ones still unknown to this day. Furthermore, it is also believed that Aleric could modify nearly every aspect of a Roblox game where it was being used. As well as its expensive emergency alert and antivirus and exploit system, it is believed that Aleric could act as an offensive weapon. There are some rumors about how the tool was used in such a manner, although these cannot be confirmed. Early warning system and event class types. A class, the most common type of event class, triggered in response to normal exploits and script injections. D class, triggered in response to moderation action against a user's property. D class, unknown. X class, triggered in response to major change and or damage to Roblox war to occur. X class events were likely triggered during the tick's removal and 2013 price floor update. Z class, Aleric would trigger a Z class event alarm if extreme damage to Roblox war to occur. Update, October 7th, 2020. On October 4th, 2020, portions of an Aleric unit's system logs were recovered. Within the aforementioned execs, the unit's security system appears to detect a class Z major anomalous event, making it the only evidence of ever such an event being detected. Said event appears to have caused universal effect to the Roblox platform, and possibly more. Interestingly, there are no confirmed records of any anomalous events happening on October 26th, 2015.