 All right. Welcome, everybody. It's really weird to be at the very first session slot of a DrupalCon. I've never done that before. It's also been more than three years since I did a talk. So a little bit nervous. It's been a while. So forgive me if I stumble somewhere along the way. So my name is Wim. I'm in the Drupal Acceleration Team at Acrea. The office of the CTO is what it was called before. And I work on various things in Drupal. And lately, I've been getting some time to push forward something that I believe is very important, even though it's not an initiative. But it helps a number of initiatives, I believe. And that's conflict validation. I made the title a little bit maybe aggressive. Next Leap sounds very boasty almost. But I do believe it enables a lot of things. And so hopefully, at the end of this talk, you'll walk out and also think that way. And maybe, well, actually no, not maybe, hopefully, know of a few ways that you can start applying this in modules that you maintain. Can I, who here maintains a module on Drupal.org? Oh, wow. OK. So that's a lot of new conflict validation that's coming soon. So let's get started. So what is this really about? Like I mentioned conflict validation, but what does it mean concretely? Well, I think many of you have seen files like this before. This is the media settings YAML files, a very simple piece of configuration. Almost every conflict module has some configuration. It typically has module name.settings.yaml. It kind of looks like this. And this looks sane, reasonable, right? There's nothing really standing out. But as I take you through the talk, you'll hopefully get scared by this because there are a number of problems here. And they're staring us on the face, but not really. That will become clear later. Actually, this is what it looks like if it's in the module itself. But once it's installed, it looks a little bit different. The config installer in Drupal, it adds this core default config hash thing, which I think pretty much all of you have probably seen before. And that's something that Drupal adds in order to allow for translatability of configuration. So that's the thing that appears everywhere, even though it's not something you specifically specify at all. So this is what it's about. And to really dissect what was going on here, I think we need a really brief history of configuration in Drupal. And I'm going to take you back to 2004. Who was doing Drupal before in 2004? I wasn't, so there's a few people here, cool. I started with Drupal 5. So for me, this is the Drupal 5 era, but also 6 and 7, because that also contained the variable table. And I wanted some simple metric to show the evolution. And so I came up with blobbiness, which is not an official term, but the blobbiness was pretty extreme back in that day. The variable table had keys, so just a string, and then a blob of configuration. And that blob really was just a PHP data structure that was serialized. So it was serialized, PHP arrays, and you could put it in there, whatever you wanted, but good luck making sense of it. So that was kind of a face balmy and a problem. So during Drupal 8, the development cycle of Drupal 8, we wanted to improve that. And so what we did instead was take it out of the variable table and into YAML files on the file system. And so that made things diffable. So you were able to at least somewhat understand what was going on in those pieces of configuration. So improvements. Then in 2013, still before Drupal 8 zero shipped, we added config schemas. I think the primary reason was for translateability. So basically there's configuration, but how do you figure out which pieces of the configuration make sense to translate or localize in every language? That's kind of impossible to know with a variable table. And the config schema that we added in Drupal 8 made it actually possible to do that. It also gave us introspectability so that you can make sense of the structure in there. So that's kind of a liable moment. It's a lot better. But then in doing that, we actually made things worse performance-wise because every single piece of configuration had to be read from the file system, parsed through YAML and so on. So in a very ironic twist, what we kind of did was take those pieces of configuration in YAML files, serialize them into PHP arrays and put them in the config table. So we're literally back to square one, but everything is exportable and everything you can make sense of. So it's definitely better, but it's kind of ironic. But performance was great again. And we actually have all of these other capabilities now. Wonderful. And then after Drupal 8 shipped, we added something else. We added validation constraints. So in the config schema, you had the ability to define constraints. And so now the blobiness became a lot better. We already made it difficult. We made it introspectable and therefore translatable. And now it's also validatable. That actually seems like pretty good blob to deal with. So the trend that we can see over time is we're adding more structure. We made it introspectable and translatable. So no more need for the variable module in Drupal 7. Anybody remember that? Yeah, I see nothing else. Translatable, we needed the I18N, the internationalization module for that in Drupal 7, not anymore. And to make things exportable, you needed to do Ctools. Ctools exportables was a thing that allowed you to export it into actually diffable files. So all of those things now come natively with Drupal 8. So let's talk about that last step. The validatability that we added in 2017, which thing is actually using that? Which is the first thing to use it? That's this one. Type UIG. And it's really the only validatable config type and that's a little bit scary. That means that nothing else is validatable. So that's not great. But before digging deeper into that, let's like, what is config schema? How many of you have touched modified config schemas before? Okay, wow. I think a third of the room or something. That's good. But for the rest of the room, this is what it kind of looks like. So for example here, every config entity has a UUID and that's defined as a top level UUID key. And so what could be in that UUID key? And that's what this meaning of type UUID is. Like what is allowed in this under this key? Well, it's a UUID. So this is using type UUID, but how do you define type UUID? How can you define your own types? And that happens in schema YAML files. Every module can provide a schema YAML file. And so type UUID, this string, this UUID refers to a top level key in a schema YAML file. So you can define keys for anything. You can do it for unicorns, horses, doesn't matter. But what matters is, you can define as many of these as you like. You can make types for things that make sense for the domain that you're working in with your module. And so you can make it make a lot of sense to you in your space, in your module. A UUID is a kind of special string. It's a very specifically formatted string. So as a storage type, we use type string. And this is again, actually a config type. You can create your own storage types if you like, but that's going very deep into the weeds. 99.9% of the time, and maybe 100 actually, you're going to be able to reuse one of the existing types. So things like Boolean, integer, string, and so on. And so UUID uses type string. We add a label that's for introspectability. And finally, we add constraints. So constraints are an optional thing. You don't have to specify it. And actually 99% of config schemas that exist today in core and in contrib do not specify this. And that's kind of what this talk is about. You start using this more because it has a lot of benefits. And so the optional key allows you to list any number of constraints. You can list zero, you can list one, you can list 10 if you like. And the structure is as follows. The key is a name of a constraint. And the thing afterwards are the options passed into the constraint. And here it's two curly braces. It's an empty object, an empty array, if you will, in YAML. So we're not passing in any options because we just want it to be UUID. We don't need to be more specific. There is no need for further detail. So this is the structure, generally speaking. And this is what you're going to be seeing a lot of. So this string, that's the last piece of like, this connects to that, this connects to that. So this UUID connects to a top-level key in a schema YAML file. Those are config types. And then config types can use or choose to use validation constraints. And here it happens to be that it's just the same name, but it doesn't need to be. It is also a different capitalization. That's how you can tell. It's definitely not the same thing. But that string refers to a validation constraint, plugin ID. So one of these kinds of annotations. I think most of you have probably seen plugins before, plugin annotations before. So it's nothing new. So any constraint plugin with AID, one of those IDs you can specify as a constraint. So this is the one that exists in Core, or the one that has first existed in Drupal Core, I should say. This one is actually kind of special. We don't define it from scratch. We reuse what Symphony already provides because Symphony is a thing that provides us with a validation constraint system. We did an event that we is in Drupal. So here we are reusing the one that is provided by Symphony. You can see here I'm using that. I'm also using the validator that comes along with it. Usually you don't have to actually specify this because it's automatically reduced by the name. So if you put your constraint in a certain namespace, say Unicorn, then you create a file called UnicornValidator and it would be picked up automatically. So 99% of the time you don't even need to do this. What you do need to do, and this is usually all that the class contains, is class, block, constraint, extents, constraint, and then a message. Like what is the message if the thing isn't valid? Maybe there's multiple, maybe there's multiple ways to be wrong. There can be multiple messages then. But this is it. So that's not too complex, I think. Then the actual validator. That's the name of the validator and it extends this abstract base class in Symphony, constrain validator. And this is really the meat of it. It's a validate method that receives a value, hence it says mixed value because we don't know anything about it yet. It could be anything. It receives a constraint, meaning the constraint is trying to validate. Most of the time every constrained validator is tied to one specific constraint, but that's not necessarily the case. Maybe you can reuse it. But we check that, hey, the constraint we're receiving is the one that I'm built for. Yeah, okay. If not, I'm going to throw an exception. And the value that we're receiving at least should be a string, otherwise I don't even know how to begin to validate it. So I'm checking at least that. And then the actual UUID validation begins. So that's kind of the structure. You have a config schema YAML file, you define a type. You can choose to list constraints. The things listed under constraints are constraint plugin IDs. A constraint plugin is a very short file that basically only needs to contain a message. And then there's a validator that sort of looks like this. I'm omitting the validation logic for UUIDs because I don't know about you guys, but I didn't realize how much complexity there is in UUIDs. Wow. So yeah, that would have been seven screenful. So I omitted that. So congrats. That's really all you need to know to be productive in config schemas. Like you know the different pieces now. You can look for examples. And before type UUID existed, what was there in Drupal core? Well, it was this. We were just saying, okay, it's a string. That means that we were literally accepting just by any string. And that's a little bit scary because if you think about how many things in Drupal built on one another, if every layer has special strings like URLs, UIDs, plugin IDs, extension names, config dependencies, all of those are strings, but none of them have a guaranteed structure. And so you can put in anything really. So it's very easy to make one mistake and have things break down along the way. So it's really important that all of the code is really correct all the time. And if we had validational strings, we would be able to detect those problems ahead of time instead of being a problem in production. So this is a change that happened in Drupal core thanks to the introduction of that one new type. And this is what we need to do for many of the strings that exist in Drupal's config schema because lots of those strings actually need to have a specific kind of value in them. So if you think about that, so if we start from UUID and think about the consequences across the whole code base, across the whole ecosystem, it's kind of mind blowing that Drupal works at all. I don't know about you guys, but I'm often faced like actually on the flight here, I was unable to check in, I tried three times online and the person at the transfer desk had to call his manager to figure out what the hell was going on. Turns out it was an IT system problem. Maybe something like this could have prevented that. But so if you think about the long-term consequences or the indirect consequences, they can be pretty drastic. So, okay, taking another step back. So in each piece of configuration or in each key value pair, we put data, but there's different kinds of types associated with it. We saw config types. So for example, this clearly is a UUID and its config type is UUID. This is coming from an actual piece of configuration in Drupal Core. It gets stored as a string and yeah, that looks like UUID, right? So thumbs up. If we look at another one, this is coming from media settings, which I showed at the beginning. So that's URI and actually the config schema type for that piece of config was type URI, great. We store it as a string, makes sense. And that looks like URI, great. But then also in media settings, we had an empty string, but actually it was type URI and it's stored as a string, which makes sense, but an empty string, that's not a URI. That doesn't make sense at all. So how was it possible that we had that in there and how did we not notice? How did we not realize? And so the config type really declares the intent what kind of value do you want to put in there? What kind of value do you expect if you read that configuration in your module? The storage type, like eventually there is no special storage for UIDs in a database, generally speaking. It's just a shape that the value fits into, like a string, any string can fit in there, but we can do further restrictions and that's kind of what the perceived and the semantics column is about. We can impose certain semantics on it because a UID is a very different thing from URI, but both are strings. So those are the different aspects that we're thinking about and what is missing and what allowed this absurd situation to happen is that we are missing validators. So we just need more of those, but it actually gets worse. It's not just that we are lacking validators. It's also that until a few days ago, we in core had tests that used this as an actual UID, it was using config type UID, it gets stored as a string, but clearly this is not a UID. So this is the thing we had validation for. So how was that possible? So it turns out that we have validators, but we're not executing them today and that's even more scary, I think, personally. So we have it, but we're not using it. That's really unfortunate. So I showed you that we went from terrible blobbiness to pretty okay blobbiness, but it's not that okay yet because we're missing lots of validators and we're not executing the ones that we have. Okay, so pause. Why do we even need to care about this? Like I took you in a journey and like in the depths of configuration of Drupal. So why would you even have to care about this? Well, it actually blocks a lot of things. For example, I worked with Matteo on JSON API. One of the frustrating things was we couldn't support out of the box writing of configuration or allowing the modification of configuration. The reason for that is that we have no validation logic whatsoever for configuration. It's all in the forms associated with the configuration, which means that we cannot execute those forms as part of JSON API receiving values. So that's really unfortunate and it affects JSON API but just the same REST, GraphQL. If the free infrastructure doesn't exist, none of them can benefit from it. Indirectly, that actually also impacts the admin UI because admin UI improvements meaning changing how forms work to make them make more sense to the end user. That means shifting things around in the form structure, which means that, for example, what used to be a checkbox and now is maybe an input type text, it allows a different value to be submitted because lots of forms, config forms in Drupal, actually do not have any validation logic at all. They rely entirely on the shape of the input element, which values those allow to be submitted. That's the implicit validation that's happening but that doesn't exist in a JSON API context because you can submit whatever you want. So there's a lot of consequences there and if we had validation constraints, we would work for JSON API REST, GraphQL but it would also allow, for example, the JS admin UI initiative, which unfortunately stopped at some point and to a large extent to my knowledge at least by the fact that it was hard blocked on not having any configuration validation. So those are two important things that would be improved. I suspect that many of you are building pretty complex Drupal sites and are using modules like complexplits and configfilter, raise of hands, who is using, wow, okay, half the room, I think. Yeah, so I was talking to Fabian Birker, who is the maintainer of these modules and he confirmed that actually there are a whole number of problems that he cannot possibly solve because there is no validation, because there is not enough strictness and what the config schema specifies. So he cannot possibly know how to correctly split or merge or filter things and because of that, it results in weird errors because the code assumes things are working in a certain way, like it receives, it assumes that configuration has a certain structure but the config schema doesn't specify it. So config split and config filter cannot possibly know what the expected result is. And so that's another thing that this has caused a lot of problems for lots of people, subtle and less subtle. And for example, for config split, he has had to actually explicitly hard code some assumptions for some very frequently occurring things in his module instead of being able to just rely on config validation. So the first two are like API and UI. The third is like kind of big DevOps related aspects but there's also significant features that would be either hard blocked or soft blocked on config validation. For example, the recipes initiative. So the goal of the recipes initiative is to be able to have pre-configured combinations of configuration that you can just import and you can get this whole feature just working. It's a recipe for success for a certain thing, a certain use case. The problem is that unless you're able to validate that whole combination of configuration, are you really sure that it's going to work on the site that it's being imported to and what if you modify it later on, if you tweak it, which of course you would want to? Is it still going to work? Is it still conforming to the recipe? Is it still going to be a working recipe or is it going to be a failed recipe? So config validation can help with that as well. In the last six months I've been helping with the automatic updates initiative and I learned something really interesting there that it's not going to be able to install hook database updates basically. So if there is a hook update N that is new, it's not going to be able to install the update because we don't know how long it's going to take to execute a database of it and we don't know if it's going to be safe and we can definitely not revert it safely. But lots of update hooks are just updating configuration. And if we had configuration validation, we would be able to see like, okay, we only are going to execute database updates for automatic updates if it's of the configuration, sorry, that actually has validation because then we can be highly confident and we could even revert. So that too is sort of blocked or it could be more helpful if we had this. And then last but not least, there are very proficient side builders in Drupal and they can use a lot of combinations of modules to build really powerful things with writing zero or very few lines of code. But you really have to internalize so many concepts and how they all interact with one another to have a working result and to make sure it really collaborates in the intended way. But if we had validation that was able to validate within each individual piece of configuration but also across, then we would really be able to verify like, yep, this is this combination of, for example, a field instance needs a field storage first, like this combination actually works. And so these are a number of things and I'm sure that some of you are thinking of additional things. These are all things that could be enabled and unblocked by config validation. So that's the potential but where are we today with Drupal Core? Well, the ugly truth is that the vast majority of config types in Drupal Core are not validatable but there is an issue to add a test to track this percentage and of course the goal would be to get to 100% eventually but for now the test we just reported and not fail. The bad is, well, actually it's good that we have every kernel test and every functional test by default as strict config schema checking but unfortunately it doesn't validate. So strict config schema checking today just means checking that the storage type is correct. So for example, you cannot put a boolean in a UUID because boolean is not a string but other than that, any string goes. That's why, for example, the first UUID example that I mentioned before was able to be in Drupal Core for years. So I want to change that and so there is this issue that is R2BC currently that would add validation out of the box at least for Drupal Core so that Drupal Core's config schema is strictly conformed to and we would think later about opening it up for a contract modules but you could opt in to this today. You could, like it's 10 lines of code you would need to add to your modules test and you would get validation. The good, however, because it's not all bad there is more config getting validatable. A year and a half ago, we added CQader 5 to Drupal Core and CQader 5 had to have a strict upgrade path from CQader 4 and make sure that every feature available in Drupal Core in CQader 4 was also possible to have an equivalent for in CQader 5 but the configuration looked entirely different. So we needed to have a way to map CQader 4 configuration to CQader 5 and make sure that the generated result was actually valid. And how do you do that? Well, config validation is what we went with. So we wrote the config validation constraints to make sure that degenerate result was absolutely valid, made sense and then we just used the same validation constraints for the admin UI that you all are using to use the CQader, to configure CQader 5 to tweak it. So you write the validation constraints once and you can use it everywhere. Six months ago, Adam Honig, Ben Mullins and I worked on starting to bring more config types into the validatable realm. And the one that we started with was config dependencies because this is something that exists in every single config entity. Every config entity can have dependencies on other modules, themes, configuration and so on. And so now that is fully validable. But again, we're not executing it today. CQader 5 is the exception, it's explicitly calling validation because that's how its UI works. But we're not using this yet, the second one here but we could. The third one that we added also a few months ago was for place blocks, the plugin that is used to render the block that you're placing. That's a string. But again, it was just about any string, we were not doing any validation. So now it's being validated that it's, or it's validation exists, we're not executing it yet. The validation exists to verify that that string actually is an existing plugin ID, so that the block will actually work. There's two issues currently RTPC or on the verge of RTPC and those are for machine name and label, which are the most widely used complex schema types. So we're on a trajectory where there's more things becoming validable, but there's still a long way to go. The good news though is that even despite this being a seemingly very short list, as we are building the constraints for these things to become validable, there are more and more validation constraints that we need to write because Symphony doesn't provide everything we need. There are more and more validation constraints that we can reuse, that you can reuse. So for example, valid keys was added a number of months ago and that can be used on a mapping to say, okay, this is a mapping, so something that contains a number of key value pairs itself. But today, any key that you want can be put in there. There is no validation at all. So valid keys, as the name already suggests, allows you to restrict that to say, okay, only the keys foo and bar are allowed. So that's already better, but wouldn't it be better still if you wouldn't have to specify those keys because you've already got the keys in the complex schema anyway. So we have that too. You can just pass the option, an option called infer. And so that infer is it from the config schema. There's more validation constraints that we added. Plugin exists to allow verification that a plugin exists. You just need to pass in the plugin manager on which it should exist because like block plugins can have IDs, but the same IDs can exist, for example, in CKether 5 plugins or in whatever plugins. So you need to pass in the plugin manager that the plugin should exist in. Extension names need to have a very specific shape. Extension exists. So for example, for config dependencies, that's where this was introduced. If you're saying that I depend on the foo bar module, then if you use this constraint, then you would be able to say, okay, this thing contains a string and it contains a module name and the module should exist. So that's what this would express. Config exists, as the name suggests. I would verify that the string is an ID of a piece of config that actually exists. So these are all validation constraints that you can start using today in your contract modules. So if you're interested to see where does this at today, what's happening currently, where does this going? These are the two issue tags to follow in the Drupal Core issue queue, but they're also being used in contract modules. So these two issue tags. So I know that I took you in a slightly even more abstract way, so let's make it much more concrete because this is all pieces and snippets from all over Drupal Core, so let's bring it into one UI. And there is this module called Configuration Inspector. Who have you have heard of this module before? Yes, only 5%, I would say. So this module is going to, if you maintain a module at all, I really encourage you to install this module later today and use this module to look at the config schema and the configuration that your module has because this is going to make it very clear what the structure is and what things are maybe a little bit off. So since version 2.1.1, it has a slightly different user interface. So if you've seen it before, there's two things that have changed essentially. There's a new column called Validatable and that gives a percentage because a piece of configuration has a whole number of key value pairs. Like there's a top level key, but there can be second level keys under the first level, third under the second and so on. So for every one of those, we check, is this Validatable? Is this Validatable? Is this Validatable? If we add those all up and look at the total, that's a percentage. And so yeah, for example, Automated Chrome is a Drupal core thing, 0% Validatable. So for example there, we have work to do. But then the data column already existed, but we changed it. So there's either one green check mark and a question mark or two green check marks or if it's neither of these icons, but an error message, then of course there's errors. So one green check mark means it's a correct primitive type, meaning correct storage type. So for example, it's a string, it's not a Boolean, it's a string as it should be. But there's a question mark because we cannot know if the string itself is correct. Maybe there's a first UID instead of an actual UID. Two check marks means all is good. So if we look at all of Drupal core, there's nothing that has 100% Validatability and there are a few problems. So here apparently there is one actual error in the schema itself. So the schema, there's something fundamentally wrong, there's something broken in it. The Validatable column shows, for example, that system theme global, the global theme settings, are 41% Validatable, not bad, but there's one error. So there's one violation of validation constraints. So if we go a little bit deeper and look at one specific example, you can see there's different views that you can go and look at. We download the YAML, overall data I think is a PHP serialized array. Form generates a form based on the introspection. List provides a listed overview, but tree is the most interesting one. So I'm gonna take you to that one and look at media settings. So you can see here media settings, the tree view. And so at the bottom here, we see that, for example, standalone URL is a boolean. And look at that, it's validatable and it lists the validation constraints. So this is using the primitive type validation constraint with no options and it says it's inherited. And here, for example, this URL, we've seen it before, it's type URI, it's validatable, this is the validation constraint and again, it's inherited. And so we can look at all of these and for example, this looks very URI ask, right? But actually it's type string. And so it's not validatable because it's just an arbitrary string. Why, I don't know why it's a string, why it's not type URI, but there you go. That's the first thing we would need to figure out and fix. So the config inspector UI makes it really possible to browse across your site, look at specific things. And actually it even has a drush UI. So you can call drush config inspect. You can limit it to the one piece of configuration you care about. So for example, in this case, media settings. So media settings, I'm asking for detail and I'm asking it to list the constraints. So here you can see those same things that we saw in the UI. You can see again that these are validatable, but then for example, icon base URI is not validatable. And this core and core default config hash thing, I mentioned this before, this is inherited, it's automatically applied when you install a piece of config. I want to improve this UI further. I'm not the maintainer of this module, I'm just a contributor. But I would like to prove it further to indicate that this is not something you need to add validation for here in media settings, it's something, it's a problem elsewhere that needs to be fixed there. So this is a very helpful way to figure out, like okay, some things in my modules configuration are validatable today, but which things aren't yet. And then you can choose how far you want to go to. Like maybe some things are like so trivial, you don't want to bother adding configuration validation for it, but some things maybe are subtle and complex and maybe they've caused lots of bug reports or support requests, and this can then really help. So if we leave Drupal core and go into Drupal contrib, then the good news is that you can start using this today in your module and you can go as far as you want. In fact, the CDM module that I maintain has been doing this not since last year, but actually since 2019. It's been possible all along because since 2017, Drupal core has had the necessary infrastructure. So I think many of you have built configuration forms for your modules that look like this, module name, settings form, extends config form base, and then there is a build form method, like just a form in Drupal, nothing special about that. There's a validate form method that reads information from the form state, meaning the values that have been submitted, does some processing and then oops, detects there's a problem, calls set error by name, and then passes a error message. The right domain is not valid, provide a host name like blah, blah, blah, blah. Okay, so validation logic. You've seen this before probably. Submit form. So after validation passes, we get to this point and we do the same dance kind of this form state that's being received. We get the form states, we assign it to configuration, which we just loaded. This is the configuration for my module. And so for every piece of configuration in the UI, I'm mapping it from the form states into the configuration object. Eventually I call config save and then I call submit form. So this probably looks familiar to you and I think we should change this to something actually slightly more simple that is actually more powerful. So what I wanna do is I wanna not extend config form base but validatable config form base. The build form method stays the same. We add one new method that's responsible only for reading information from form state and mapping it to the corresponding config. So that's what I do. So it's the same logic, I just copy pasted it and instead of saving the config, I'm just returning the object. So now the object actually corresponds to the data that was submitted by the user in the form. And then if the revalidation errors triggered by the validation constraints, we need to map those from the property paths, meaning the exact location in the configuration file into the corresponding place in the user interface. So for example, I have a mapping top level key and under that there's a domain key that has a value and if there's an error message, that was not me. If there's an error message, I need to map it to the proper place in UI. And so in this case, it looks like this, that's a form name. So the name element of your forms for your form items and that's really all there is to it. So we didn't change anything drastically. We are stopping to call save explicitly. We can reuse all the logic we already have in a submit form method. We just move that into a different method and the one thing that we need to add but that we actually already had before too but just looks different now is mapping one string to another property path to a place in a form. And if you do that, ta-da, it just, it works. It's not complicated. And so you can start using exactly this pattern today. You can copy the validatable config form base from the CDN module. It just extends this thing that you're already using anyway. So you wanna subclass that then instead of config form base and there you go, you're off to the races. It is actually validatable. And for the CDN module, it specifically made a big difference because there were very many subtle misconfigurations that led to so many bug reports and support requests and that like has been cut in by 10 fold easily. There is one extra thing you can do optionally because right now, like at this point, all that's happening is validation is happening when they use your UI. But what if you also wanna make sure that things are valid when they are importing configuration through configuration management? Well, then you can optionally add a config events save subscriber and then you can choose to validate your config. You shouldn't validate all config because not everybody has added validation constraints yet but you know for a fact that your module now has the necessary validation constraints so you wanna call it always so that you don't get bogus bug reports because it was validatable anyway. So you can do that too and then this error message, note that the exact same error message appeared here during config import, it's 10 lines of code. So you can copy that too from the CDM module. So if you're looking for examples because the CDM module at this point is definitely not the only one that's using this. This is a QR code for scanning all of Drupal contrib for constraints in all schema YAML files. So there actually are dozens upon dozens of examples at this point and chances are there are a number of them that are close to what you need to do or we'll find at least examples close to what you need. So how can you start adopting this on your concrete projects instead of Drupal modules specifically? If maybe there is a project that you've been running into problems with configuration with. Well, you can start with analyzing your entire site the draft command that we saw before but no restrictions, just do everything. Export it as a CSV file then open it in a spreadsheet application sort by validatability to find the easiest next target so for Drupal core apparently the easiest target is user settings which is largely validatable but not entirely. So I'm now going to live show how to add validation for one additional thing in user settings and I hope that it's going to shock you how easy it is. So we're again going to start with trash config inspect and we're again going to filter to the one thing that we care about user settings is the one thing that we're trying to improve right now we're again asking for details and we're asking for the constraints to be listed. So if we look at this I removed some of the lengthier ones but like the percentage is the same one we saw before we already know that these are not for us to solve it's a problem elsewhere in Drupal core so the first one we need to solve is anonymous it's not validatable and yeah there are a whole number of things here that are validable so let's start with anonymous. So anonymous in the user modules schema so user schema YAML user.settings is a top level key and then anonymous under that this is what it looks like today. So this is just the thing that by default is set to capital A anonymous that's the name of the anonymous user you can call it visitor or you can call it interested person you can call it whatever you want but it should be a sensible value because otherwise for example emails may tell that anonymous has commented but then like there is nothing in there that makes sense. So there are some restrictions for example should not be blank should not be the empty string because then the UI doesn't make sense the emails don't make sense that's the first restriction I added the first validation constrained no code written just one line of metadata and then I figured like well maybe we also need to be a little bit more specific it should not just not be empty it should also be something that works in all contexts so there needs to be some alphanumerical character at least so it's not just emojis for example because that doesn't work in all contexts so I added a regex that requires it to be at least one alphanumerical character and then we need to update the form to actually call the validation constraints to use validatable config form base so okay which form is using it turns out that user.settings is manipulated by five or so forms in Drupal core so how to find the right one and I have a pretty cool trick with PHP storm that hopefully some of you are going to find useful so what I'm doing is I'm filtering by mask so I'm looking at all forms I know that config form base has this method that we have to implement called editable config names so that lists the names of configuration that that form can edit so I first look for that so now I have all the files that implement that method and I click this button open and find window and then as a second step I search again I keep the same file mask but you can even omit that I search for user.settings which is the thing I cared about and then in here you can set the scope to the files of the previous search results so now you're restricting to the matches that you had before so now I'm searching only in the files that I know are going to be relevant because user.settings is used in lots of places also in non-form places so now there's only one result account settings form wonderful and it looks like it has three things of three pieces of configuration it's editing okay so let's look at account settings form and let's start with changing it from config form base to a validable config form base that's change one change two is submit form it had this logic for mapping from form states to a corresponding key in the configuration so I'm cutting all of that away and note that there is a save here so I'm cutting that it's in my clipboard and I'm pasting it in a new method I'm pasting it in a new method called map form values to config so same responsibility from form states to config objects but because there's many pieces of configuration this particular form was editing I need to look at like okay which piece of configuration am I mapping the form values for at this time so right now I'm checking only if it's user settings and if it's user settings I paste the thing I just cut omit the save and that's that's all I did so I think we wrote six lines of codes in total something like that and it works that's all you need to do so you can very powerfully change a few lines of code to execute validation constraints in your existing UIs add a few lines to your config schema and have it actually all be validatable in configuration so this is a message I specified in a schema file just an emoji and we get it so that's great and I think it would make sense for a validatable config form base to live in Drupal core so this is the issue to hopefully add that to Drupal core and that's really where we are today so I hope that you found some ways that you can start using this today and it's just not just me at all who's been working on this I have a person who's been doing a lot of reviews lately Adam Honig and Ben Mullins who have been helping a lot with those initial config types to be validatable Fabian Berger who's modules a lot of you are using for config split and config filter and then Daniel Vayner and Alex Potts who've been doing a lot of work on config schema years ago and we were trying to get it going back in 2018 Alex Potts is still trying to help that happen so hopefully with these people and hopefully some of you we're going to be able to get all of Drupal core to get to the point where everything is validatable so what does the future hold? Well the challenge is definitely going to be that for a long time things are only going to be partially validatable we're not going to go from one release to the next and everything is going to be validatable especially if you consider the fact that for example say you are using the views module you have a view configured and say the views magically had all of its config schema validatable which is the most daunting thing to add validation for so say that all of Drupal core has config schema stuff validable for views but then there's contract modules that add new plugins for views and then those are not validable so 99% is validatable but then the extensions provided by contract modules are not how to deal with that, that's tricky but hopefully we're going to start seeing things like for example JSON API be able to offer you to write and so create and modify a config through JSON API for the pieces of configuration that are fully validatable at least same for recipes recipes I hope will be validatable and maybe the ones that are validatable are have a higher degree of trust for example but it's not just functionality that still needs to be built it's actually some very low hanging fruit as well because once there's configuration that's validatable you can actually improve the reliability of your Drupal sites, your builds by just running config schema validation within CI on every commit that you make and modules that many of you maintain will become a lot more maintainable so thank you and the meta issue to definitely look at to see all the big picture stuff that's happening it's this first one and again a QR code to make it easy for you to follow these are the three issues that are the most important that are happening right now and are either RTPC or close to hopefully and then the last one is like kind of future thinking this was opened I think in 2016 or 17 by Daniel Vayner because validation is one of the things we could do or we can do today with config schema but there's actually much more we could do we could add much more metadata that makes it much more rich in describing what this data is what it can be used for and it would enable much richer experiences and user interfaces so any questions that you have and I'm curious to hear from all of you which config changes have caused oddages or problems and nightmares for you thank you no questions at all that works okay so the question is what would be a realistic timeline for all of Drupal Core to be validatable maybe Drupal 11 I was pessimistic until a few weeks ago but then I was working hard on some of the issues listed on the screen right now and it turned out to be more feasible than I had thought so I personally think Drupal 11 is super feasible but then, for example, there needs to be a commitment of at least a few people to work on it for a significant amount of time but it's doable but the cool thing is you don't need to wait for Drupal 11 you can start using it in your modules today but yeah, fair question I don't know all right well, have a great DrupalCon and I'll see you around