There are many great git workflows out there, but sometimes you just can't find the one that perfectly fits your needs. For us the need rised in the support & continous development where our projects and workflows weren't that simple and clear. No existing workflow fit our need and after testing and reviewing many we decided to start working on our own.
Most of the established git workflows are tailored around single product or project. They do work well before the project is published or when the release process is handled inhouse. But for established sites with ongoing improvements when all the new features need to be shown to customer and accepted by them they caused more problems for us than they solved.
Ok, so let's get started, here is how it works:Base branches:
In WunderFlow we have three main branches each having their own distinct purpose.
Production branch is always the branch that holds the version of code that is deployed to production. This is the branch is also used to branch hotfix branches.
At any time master branch should contain only working, tested and release ready code from new features. Any new feature should be branched from this branch. This branch should also be used for any automated testing or any other quality assurance processes. New releases are made from here by merging this branch to production (and possibly tagging the release). Any hotfixes made to production branch should be rebased here as soon as they are released. Those two branches are quite in par with the git-flow so basically so far our flow can be used as a drop in replacement for it.
Our first big difference here is the development branch. First of all it is the safe playground for experimental code, testing and debugging. Anything can be committed here, but nothing living only in this branch will ever end up in production as this branch will never be merged upstream. Instead this branch can be at any time be reset to master discarding any wild code residing only in here. Secondly sometimes there are projects that have for example such integrations that can't be reliably tested in local / test environments. This is handy when you need to test new features relying on those integrations, or you need to debug some issues with them with current production code & data. Finally this gives you a nice environment to display your current progress or sandbox features to the customer. There are great solutions like platform.sh or Pantheon that give you working environment per branch, but with customers this is usually not convinient for them. They prefer having single environment they can easily remember (e.g test.theirdomain.tld) and bookmark. This way they can also have an environment where they can input testing content to test new features without having to input that content to multiple environments just to test different features. This also helps with the integrations mentioned earlier.
Another "new" feature in our workflow is the concept of epic branches. Often while developing bigger stories they need to be broken into many smaller features usually depending on each other. The case might be that the whole story need to be released at once, or it can be that there are some features that can be put into production earlier. Our epic branches are the tool to manage such situations. In essence epic branch is just a temporary branch that functions as a master branch for certain set of features. Everything that applies to the base workflow applies here just by substituting master with the epic branch.Simple example:
Let's say you have a user story about a new content type that needs to be added to the site. There should also be new view listing the content of that type. You have next release coming in 2 days and it's not sure if you can finish the whole story by then. The customer also wishes that they should be able to start inputting the new content as soon as possible, even if it wouldn't still be possible to display that content in any listing. You also already have some new features waiting for the release. Clearly a case for epic branch.
So, you create a new epic branch for the new content type and listing, let's call it epic/NewContent. Then you start working on the new content type creating a feature branch from the epic branch: feature/NewContentType.
After getting everything ready you can push that branch to epic and that in turn to develop so that customer can review it and comment if there is need to add or change anything.
While you wait for customer to review that work you can now create another feature branch from epic to start working on that listing view: feature/NewContentList. In time that can also be merged to epic and ends up to develop for review.
Now during the remaining time before the release there are different scenarios that can happen:
1. New content type is not accepted by the customer. So nothing from this story end up in the release.
2. Customer accepts the content type and wants to include it into the release so they can start inputting content while they wait for the listing feature to be finalized. You just merge the feature/NewContentType branch to master and do your release.
3. Both the content type and listing features are accepted by the customer. You can merge the epic/NewContent to master and do your release.
As it's always hard to estimate how long developing something can take and also how fast you can get review feedback for your work you need to be prepared for different situations. With WunderFlow it's easy to be prepared for those different scenarios. As this was just a simple example but imagine there being more of those similar stories, some smaller features and couple of hotfixes happening at the same time: you'd still have the same options of choosing easily what goes to the next release with clearly separated features and the possibility to work on new features depending on other features.
Most up to date definition of WunderFlow can always be found at http://wunderkraut.github.io/WunderFlow/
Irony presents itself in many forms. Not being able to login to a site that is responsible for testing that the login is working properly on other live sites, is one of them.
As much as I'd like to say I was able to enjoy the irony, the six hours I spent tracking the bug were slightly frustrating.
One of the things Shoov is built for is assisting us with a quick configuration of live site monitoring using your preferred functional testing tool (e.g. Behat or CasperJS).
As awesome as services like Pingdom are, they still provide very little insight to what's actually going on in the site. In fact, according to Pingdom, Shoov was up and running, even though no user could have logged in.
At this point of time I think very few people care about the "post mortem" of this incident since Shoov is still a work in progress, however some interesting lessons were learned, and some contributions were made.
Awhile back I posted a video on setting up a Drupal sub-theme.
Drupal core announcements: Drupal 8 theme system critical issues sprint (June 5-7 in Portsmouth, NH)
Join us at the NHDevDays 2 sprint in Portsmouth, New Hampshire June 5-7.
The sprint will be focused on resolving the two remaining theme system criticals around autoescape and SafeMarkup:
- #2280965: [meta] Document or remove every SafeMarkup::set() call
- #2273925: Ensure #markup is XSS escaped in Renderer::doRender()
Thanks to funding from the Drupal Association via Drupal 8 Accelerate to cover travel expenses two of the Drupal 8 theme system maintainers – joelpittet and Cottser – will be in attendance leading the sprint and providing guidance.
We recommend you have Drupal 8 installed before the sprint and if possible have some experience working on Drupal core (attending core contribution mentoring hours would be a great way to get a kick start!).
The theme system maintainers will be giving a brief overview of text sanitization and autoescaping in Drupal 8 and you will learn more about working with the theme layer in Drupal 8.
We also welcome remote attendees, join us in #drupal-twig and RSVP – there is a remote sprinter option when registering.
This is a recap of our session from Drupalcon 2015 in Los Angeles.
About 6 months ago, the Drupal security team announced one of the worst bugs in the history of Drupal. The recovery period has been very challenging for our community, though I think it's safe to say now that the storm has passed.
One of my personal sites, http://whaleocalypse.com/, was affected by the attack. I've been able to verify that the attack I experienced was the same attack that an overwhelming majority of Drupal sites experienced. What follows is a comprehensive post-mortem on that attack, including how it was done, and how you can ward off similar attacks.
A couple of disclaimers before I begin. First, I'm going to confess to some very insecure practices on whaleocalypse.com. Understand that whaleocalypse is a play thing, I knowingly took huge risks with that site because I had nothing at stake if it was lost. Quite honestly, I was pretty excited to learn that this disposable site been hacked because it gave me the opportunity to learn more about security. I would never take these same risks with my professional client work.
Second, and perhaps more importantly, I'm going to reveal how this hack was pulled off in very, very specific detail, including a large amount of fully functional exploit code. Checkout the code on Github. If at any point you feel yourself going "Hey, you're telling people how to hack my site!" I'd invite you to stamp that feeling down. If you are still vulnerable to any of the techniques described here, I'm sorry to say, you were already hacked weeks ago.Table of Contents
- How This Hack Works in the Wild
- How This Hack Works in the Wild: Video Explaination #2
- Why create all these backdoors?
- Was This Really Drupalgeddon?
- How I Recovered
The problem lies in database.inc, specifically in the function expandArguments(). Note lines 739, 745, and 755 in that file. It might be a little hard to follow, but the gist is that Drupal trusts the value of $i on 739 without sanitizing it. This is a problem because, in the case of the user login form, $i is generated based on the name attribute of the html <input> element.
Which means this hack just so, so, so easy to pull off:
Using this vector, I trivially worked up a little drupalgeddon client that will allow me to inject complex SQL statements into any vulnerable site.
Here it is in action:
Checkout Stephan Horst's examples to get a broader sense of what's possible with this bug.How This Hack Works in the Wild
It's all well and good to talk about the theoretical danger presented by this bug. What I want to know is: how was the bug actually used in the real world by the real hackers who broke into my site. In order to answer this question, I spent a great deal of time examining the exploit files left on my server, and reverse engineered the tools that would have been used to create them. Check it out on Github.
I want to note here that, according to data released by Acquia 68% of hacking attempts in the first week of druppalgeddon were of the variety I'm going to describe here. The second most common attack style—adding a new admin user—accounted for 26% of all attacks. The user add style of attack is well understood, so I won't go over it here.
The attack that I, and most drupal site owners, experienced I'll call the "menu_router" attack. It works as follows:
- Create a new entry in the menu_router table whose "access_callback" is file_put_contents and whose "access_arguments" are a filepath and the contents of a file. This creates a new page in drupal to the effect of http://example.com/backdoor, where "backdoor" is a random string.
- Visit the new exploit page http://example.com/backdoor. When Drupal checks to see if the user should have access to the page, it will run file_put_contents('path/to/backdoor.php', '<?php //contents of attack file here ?>'). This creates a backdoor file which allows the attacker to execute any PHP on your server.
- Using the newly created backdoor.php, run some code which will make a request to another server and download a secondary attack file. This secondary attack file is a file upload form. It gives the attacker the ability to upload any file to your server.
Also, here's another video overviewing the whole exploit kit, and the defense kit.
Video table of contents:
- Intro 0:01
- The Anatomy of a Hack 0:55
- Step 1: Inject the SQL 4:17
- Step 2: Create a Backdoor to run PHP code 10:54
- Step 3: Create a Backdoor to Upload Files 13:14
- Defense procedure 1: prevent SQL injection 22:21
- Defense procedure 2: prevent malicious file uploads 29:01
- Defense procedure 3: prevent arbitrary code execution 34:15
Using some strategy akin to the SQL injection tool I showed above, the hacker would have inserted a new row into the menu_router table. That row looked like this:How to Defend Against This: Drop All POST Traffic in Varnish
If you haven't yet, UPGRADE TO DRUPAL 7.32 OR HIGHER. If you are reading this, and you are running a Drupal site on version 7.31 or lower, your site has already been hacked, probably several times by many different individuals.
That said, this is a good opportunity to harden your site against all SQL injection. If your site has a handful of logged in users, and serves mostly anonymous traffic, one precaution you can take is simply rejecting all POST data in Varnish—almost all SQL injection vectors will make use of POST traffic. You can do this trivially in your VCL file like so:
Site administrators can still login by visiting Apache directly on its new port, which is now 8000. You'll prevent non-administrators from visiting Apache directly by using an IP access control list in your Drupal .htaccess file. To accomplish this, simply prepend the following to your htaccess file:
Now, when a hacker tries to POST to your site they'll get an error:
See: Defense Procedure 1 at 22:20 in my video above.Step 2: Create a backdoor that allows you to run any PHP
Now that we've created our menu_router entry, it's time to visit our new page. When we do so, a new file will be created.
As soon as the attacker visits this page, assuming your file system is writable, the following file will be created:
I spent a long, long time staring at this file during my post mortem. It was finally this comment on drupal.org that cracked the case for me. Can you tell what it does? Spoiler alert! It's a backdoor that allows the attacker to run any PHP code. Once this file is installed on your server, all the attacker has to do to execute PHP is send an HTTP request like so:GET /modules/poll/zkwv.php HTTP/1.1 Host: exploited.com Cookie: Kcqf3=base64_decode; Kcqf2=["preg_replace", base64 encoded]; Kcqf1=[any PHP, base64 encoded]
I've reversed-engineered a deobfuscated version of it, to make the inner logic visible:How to Defend Against This: Set Proper File Permissions
Its worth noting here, that the most common attack seen during Drupalgeddon would have failed on any site that had set proper Unix file permissions. If you haven't already, you can do so automatically with this script. See Defense Procedure 2 at 29:00 in my video above.Step 3: Create a backdoor that allows you to upload files
Now the hacker has the ability to run any PHP on your server. And of course there's a great deal of damage that is possible with that power, but I've been able to determine what this hacker actually chose to do with this power. In addition to the arbitrary code execution backdoor I demonstrated above, I found several attempted backdoors. The most telling was this one, which I found inside the locale module:
Note, that is not my 404 page, that is the attacker's 404 page. Which means my server tried to execute some code intended to download a file. Which also means that we can go and see what file the attacker was trying to download:
I recognize this file! All told, I found four copies of this file on my server, and two copies of 404 pages in which the attacker attempted to download this file. When you compile it into HTML it's an uploader page, which will allow the hacker to upload any file to your server:
So not only do I now know what code this attacker executed and what it was for, I know the name of the town in Romania where he or she is fromHow to Defend Against This: Upgrade to PHP 5.5.0
Remember, this is the second of two backdoors the attacker is going to install, and it is wholly dependant on the success of backdoor number 1 (which gave the attacker arbitrary code execution). Backdoor #1 is wholly reliant upon a weakness in preg_replace which allowed you to evaluate the haystack as PHP. This weakness was removed in PHP 5.5.0.
So while the attacker might still get backdoor #1 installed, they won't be able to use it, and they will not be able to create backdoor #2.Putting it All Together
Considered together, you come up with a script like this. This is my best guess at the script this hacker actually used to attack my site. Once a hacker has executed this script against your site, he or she will be able to inject any SQL into your database, run any PHP on your server, and upload any file to your server.Why create all these backdoors?
OK, if I may speculate wildly for a moment: this attacker was not interested in changing any content on my site. They didn't deface the homepage, or use my server for spam as far as I can tell. All they did was install obscure backdoors with random file names. So if I had to guess, the goal of this particular attack was to compile a large database of backdoored sites, and then sell the database. So maybe eventually this could have been used to steal data, but that doesn't seem to have been the direct goal of this particular attacker.Was This Really Drupalgeddon?
In a word, no. A two words, not hardly. In a gif:
Let's just review some facts:
- Anyone hosted on Acquia, Pantheon, Blackmesh, or Commerce Guys Platform.sh was safe, whether or not they patched.
- Anyone who's file system was unwritable to Apache was safe from the most common attack.
- Anyone running php 5.5.0+ was safe from the most common attack.
The discussion of this bug has so far centered largely on it's potential for damage. And, fine, I admit in theory this could have been really bad. But here in the world where we actually live, it's just impossible not to notice—nothing bad really happened. I've read lots of cases of hackers creating fraudulent users and uploading backdoor files, but I have yet to find—despite considerable effort—a single person blogging about a `DELETE FROM node` attack. As I learn more and more about this bug, I am increasingly persuaded that such an attack did not occur.
As Stéphane Corlosquet wrote on the acquia blog, across tens of thousands of (failed) hacking attempts, none were destructive, or even visible to the end user:
We could not find any query intended to change the content or destroy sites: attackers were only interested in installing backdoors to take over the site or server at a later point in time, and make the intrusion unnoticeable.
So just a casual suggestion among friends, but maybe we should stop analogizing this bug with the literal end of humanity and start regarding it as what it was: another day in the life of a sysadmin.How I Recovered
TL;DR I restored from backups. Blair Wadman gives a pretty good overview of what it takes to secure your server, but briefly I:
- Used the drupalgeddon tool to check for exploit files (it found all of them, by the way).
- Copied my whole codebase from the server down onto my desktop and diffed them against the last known good version in git (this is how I know the drupalgeddon tool worked).
- After 360 days and 5 hours of continuous uptime, I re-installed Linux from scratch. It's a good thing too, because I've been meaning to patch the shellshock vulnerabilty (lol).
- Deployed my local backups to the new server.
I just want to close by saying that I think this security event could have been a lot worse. The big Drupal hosting providers were patched before the vulnerability even became public, so very few high value Drupal targets were hit. Of the Drupal sites that did get hit, the most common attack seems to have been pretty innocuous. This is a case where open-source worked more or less as it's supposed to; more eyeballs on the problem brought an incredibly obscure bug to light, and let us fix it—whereas a closed source product would have kept chugging along with the vulnerability unpatched. While this has not shaken my faith in Drupal as a whole, it has made me sit up and take security a little more seriously.References
It’s almost that time of the year, where we get the Drupal community together in Europe to celebrate and share amazing stories. In Front end we are coders, designers, and sometimes both. We build themes, work with developers, designers, project managers, content strategists, marketers and clients. We are looking for a mix of topics that will inspire and excite us.
The Front end track will have 13 sessions and we would like to cover the following topics:
Drupal core announcements: Formal usability testing of Drupal 8 at the University of Minnesota Usability Lab, 22nd–25th June
On the 23rd–25th of June, just before Twin Cities Drupal Camp, we will be conducting usability testing focusing on Drupal 8 at the University of Minnesota. This is a great opportunity to evaluate the current state of Drupal 8 and identify issues that can be resolved before release, or require much of our attention after release.
We'll start on fixing items found during the Twin Cities DrupalCamp Sprints and continue throughout Drupal 8's release cycle.
The University of Minnesota's Usability Services Department has been an amazing long-time supporter of the Drupal project. Hosting us in 2008 just after Drupal 6's release for the first-ever Drupal formal usability study, and again in 2011 just after Drupal 7's release. These usability test results have been invaluable in shaping Drupal's user experience over the years.What will we be testing?
The tasks for this study will varied and focused around both content creation and site building activities:
- Mobile content creation experience
- Content authoring (preview, menus, in-place editing)
- Layout modeling (placing blocks and editing blocks)
- Content modeling (Field UI, Views)
We will be inviting users with a technical background, of which at least half have experience with Drupal 6/7.
We are close to release thus we have a small window of opportunity to fix these problems before Drupal 8 is released.
- Review the test script (should be ready next week, to be finalized by June 15).
- Help find and fix any major user-facing bugs prior to Beta12 (June 17) that will get in the way of users completing the test script. File these under the UMN 2015 prep tag.
- Attend the usability testing, either in-person or remotely (see below).
- Contribute during the Twin Cities DrupalCamp sprint (in-person or remotely in #drupal-usability) to translate problems that were found into actionable Drupal core issues.
- Provide solutions/reviews to the identified issues with the UMN 2015 tag.
While space is limited, we are able to accommodate some community members who wish to attend the usability testing sessions either in-person or remotely (over WebEx). In case you are interested please get in contact with Lewis Nyman.
We know that experiencing a usability are quite transformative, and hope that anyone interested reaches out. Sadly, the sessions will not be fully open - as we wish to respect our participants' privacy. Attendees will be required to sign the University of Minnesota Usability Lab's Code of Conduct in order to ensure the privacy of testing subjects is upheld.
We are very excited about learning more about our users and Drupal, and hope to share the results with you as soon as possible!
One of the most commonly used modules for helping with a Drupal 7 site’s SEO is Metatag. A rewrite of the Drupal 5 & 6 module Nodewords, Metatag provides a flexible system for customizing the meta tags used on a website. Using various meta tags it is possible to exert some control over how search engines analyze each page, and how the content looks when it is shared over social networks.
Midwestern Mac, LLC: DrupalCamp St. Louis 2015 - register now, come help at our first-ever sprint day!
DrupalCamp STL.15 (June 20-21, in St. Louis, MO) will be the first DrupalCamp in St. Louis with a day dedicated to sprints to help the Drupal community. We're expecting a great turnout, and there are already a number of proposed sessions (many of which will be selected and announced on June 5!), and it's not yet too late to propose a session of your own!
This year's keynote, by Alina Mackenzie, will focus on the Drupal Community—what it is, why it rocks, and how you can get involved in the community. After the keynote, some great sessions, a tasty lunch, happy hour, and a good night's rest, we'll spend sprint day (Sunday June 21) making Drupal better, and maybe even pushing Drupal 8 a little closer to an 8.0.0 rc1 release!
Registration is now open, so go reserve your spot at DrupalCamp St. Louis 2015; I'll see you there, hopefully at one of the sessions I proposed, either on High Performance Drupal, or Local Development Environments and Drupal VM!
Yes, yes, one click deployment is amazing. And yet so last year. So I say, hell no, we want one push deployment. The dream cheeky USB button is neat. Let's deploy sites with it. This project is an example of how you might be able to do it: Deploytron.
Ok, so what does this really mean? With virtualized development environments, continous integration tools, and continous delviery tools we should be able to make changes to production sites predictably and easily. Deployment isn't an after thought, it's simply another step in the development process. And its easy. Hosting services are marketing tools to do specifically this. But frankly, it takes the fun out of it.
You should be able to launch a site with some fan fare. Deliver a Deploytron box to your client and let them hit the button. Put names in a hat and let somebody in the office press the button. See how long it takes your cat to step on it.Categories: Planet Drupal
The next beta release for Drupal 8 will be beta 12! (Read more about beta releases.) The beta is scheduled for Wednesday, June 17, 2015.
To ensure a reliable release window for the beta, there will be a Drupal 8 commit freeze from 00:00 to 23:30 UTC on June 17.
Recently, I had the opportunity to present my core conversation,”Pain points of learning and contributing in the Drupal community,” at DrupalCon Los Angeles.
My co-presenter Frédéric G. Marand and I talked about the disconnect between Drupal and api.drupal.org on core and some of the pain points to contributing and learning in the Drupal community. We also spoke little bit on continuous contribution and sporadic contribution and benefits of both.
The open mic discussion brought up some interesting issues, and so I have compiled some links to answer questions.
Audience Suggestions and Responses
- Stable release of Drupal 8 will help people start on client work and support contribution. The Drupal community needs to recognize contribution not just in the form of patch, but mentors mentoring on IRC during core office hours, credit to code reviewers on the issue queue, recognize event organizers and have people edit their profile on Drupal.org and list their mentors at the end of a sprint.
- We now have an issue on Drupal.org to allow crediting for code reviewers (and other non-coders) as first-class contributors.
- Make profiles better on Drupal.org. Here is an issue for that – [Meta] new design for User Profiles.
- Event organizers could get an icon on their profile page. You can read more on that – Make icons for the items in the list of user contributions to be included on user profiles
- Another issue to read – Reduce Novice Contribution differences and consolidate landing pages, content, blocks
- Explanations of what needs to be done could be a big time-saver. For Drupal 8 there are pretty clear outlines of what could be done for core.
- There was a suggestion to provide video and audio documentation instead of just text, walking people through issues. There are four or five companies that make videos and we have core office hours for walking people through the issue.
- A few people expressed that its hard to keep up with IRC and are looking for easier ways to communicate. I have created an issue for that and you can read more here – Evaluate whether to replace Drupal IRC channels with another communication medium.
- Another audience member suggested that we need to make sure that communications that happen in IRC are summarized and documented on issues so more people can get familiar with the discussion.
- There were some suggestions for core mentoring that have been proposed but haven’t panned out such as twitter or hangouts (privacy concerns, less office-friendly)
- Someone suggested that those who don’t like to get on IRC, can get core updates via email (This week in Drupal Core) which is a weekly-to-monthly update on all the cool happenings in Drupal 8
- Users can also subscribe to issue notifications in email on the issues/components they want to follow on Drupal.org.
Overall it was an enlightening core conversation and it was amazing to hear from the community about their pain points and suggestions they made.
Jeff talks to Deane Barker of Blend Interactive about the art and practice of content management, the joy of solving complicated problems, and his upcoming O'Reilly book Web Content Management.
Before anything else, I want to point out that while this post will focus on maintaining a contrib module on drupal.org, that is just one of the many ways to contribute to the Drupal project. Every contribution is important whether it's a core patch, a documentation edit, a translation, or something else. If you use Drupal, please consider how you might be able to give back to the community. If you're already contributing, then thank you!
In April 2015, I was excited to talk with John Doyle, General Manager Technology & Solutions Architecture at the Australian full-service digital agency Komosion, to explore their decision to adopt Drupal to replace other technologies, including an in-house CMS they'd invested 10 years of work in. In this podcast, John very clearly lays out what Komosion's priorities were in making this decision, the benefits for the agency and its clients, and the future he sees using Drupal as the basis for future work.
It came up multiple times at recent events that it would be very helpful for people significantly working on Drupal 8 critical issues to get together more often to talk about the issues and unblock each other on things where discussion is needed. While these do not by any means replace the issue queue discussions (much like in-person meetings at events are not), they do help to unblock things much more quickly. We also don't believe that the number of or the concrete people working on critical issues should be limited, so we did not want to keep the discussions closed. Here is the recording of the first meeting from today in the hope that it helps more than just those who were on the meeting:
Unfortunately not all people invited made it this time. If you also have significant time to work on critical issues in Drupal 8 and we did not include you, let me know as soon as possible.
Last week, some colleagues from Cocomore and I attended DrupalCamp Spain 2015. Spanish Drupal community is awesome, and they have put all their efforts in making an unforgettable event again in this 6th edition (the 5th I have attended).
The event was divided into different activities for the three days: Business Day and Sprints on Friday, and sessions on Saturday and Sunday.
On Wednesday’s blog post, we debuted our first interview from DrupalCon. If you missed the Roundtable Interview, you can catch the first episode here. The interviews first appeared during our weeklong live broadcast with Periscope and Twitter.... Read more
Barcelona is one of the most cosmopolitan cities in Europe and we want to infer the same spirit for the Coding and Development track. This is an exciting moment in the web development industry and we plan to take advantage of that. The DrupalCon Barcelona Coding and Development track is focused on preparing developers for the future of the web development universe.