Merge pull request #26 from rakatyal/raghav/docs

Proposal to improve Cordova documentation
diff --git a/proposals/CLI-Templates.md b/proposals/CLI-Templates.md
new file mode 100644
index 0000000..eaeb7b5
--- /dev/null
+++ b/proposals/CLI-Templates.md
@@ -0,0 +1,32 @@
+## Cordova CLI Create with Template argument
+
+
+
+This proposal is to update the Cordova CLI to support the argument --template for create command
+
+    $cordova create myApp --template=<NPM ID | GIT URL | Local Path>
+
+- NPM ID is a npm package name with optional version
+- GIT ULR is a git url, similar format as adding platforms and plugins via Git
+- Local Path, is a local directory 
+
+- This will allow to specify the IBM NPM Cordova Template like $cordova create myApp --template=cordova-app-hello-world or $cordova create myApp --template=cordova-app-hello-world@3.9.x
+
+--template is a bit different from --copy-from, it copies everything from the template including hooks, res, config.xml, hooks, dot files (.gitignore) (it will also copy plugins and platforms but this is not recommended since templates should be small, and platforms and plugins can be specified in config.xml)
+
+--copy-from will just be an alias to --template
+--copy-from will mark deprecated and later removed
+
+If user pass any of the optional arguments for the app ID, NAME it will put those values in config.xml even if the template contains a config.xml
+
+if the template is missing certain files or directories it get's default ones here is the list:
+config.xml a default one is created  from cordoba-app-hello-world
+hooks/, the default hooks with readme is created
+www/, is missing the default is created from cordoba-app-hello-world
+
+### References:
+- [JIRA CB-9964](https://issues.apache.org/jira/browse/CB-9964)
+- [Discussion](https://github.com/cordova/cordova-discuss/issues/5)
+- [Lib PR] (https://github.com/apache/cordova-lib/pull/339)
+- [CLI PR] (https://github.com/apache/cordova-cli/pull/226)
+
diff --git a/proposals/ImprovedDocumentationGenerator.md b/proposals/ImprovedDocumentationGenerator.md
new file mode 100644
index 0000000..0e2aad8
--- /dev/null
+++ b/proposals/ImprovedDocumentationGenerator.md
@@ -0,0 +1,159 @@
+Doc System Improvement Proposal
+===============================
+
+## Motivation
+
+Our current docs are becoming slightly out of date and not keeping up with our development pace. The current docs system has a high latency and steep learning curve for maintenance, and it has started functionally and visually lagging behind docs for related technologies (see [react][react_docs], [unity][unity_docs], [ember][ember_docs], [angular][angular_docs], [ionic][ionic_docs]).
+
+This proposal aims to accomplish the following three goals for our documentation:
+
+- add a search feature
+- make contribution very easy
+- set up automatic deployment
+
+Below is a formalized list of requirements that are proposed for the Cordova docs.
+
+## Requirements
+
+The following features must be supported by the Cordova docs.
+
+<dl>
+    <dt>"edit on github" buttons</dt>
+    <dd>
+        Can easily submit changes to the docs via a PR on GitHub by clicking on an "Edit this page" button or something similar.
+    </dd>
+    <dt>search</dt>
+    <dd>
+        Can search through the full text of the docs.
+    </dd>
+    <dt>doc versions</dt>
+    <dd>
+        Can browse and change docs for any Cordova version.
+    </dd>
+    <dt>localization</dt>
+    <dd>
+        Can easily translate the docs into and/or read the docs in different languages.
+    </dd>
+    <dt>API docs</dt>
+    <dd>
+        Can automatically get generated docs for public APIs (plugins, cordova-lib, cordova-js).
+    </dd>
+    <dt>analytics</dt>
+    <dd>
+        Can have analytics for the docs website.
+    </dd>
+</dl>
+
+The following features are nice to have in the Cordova docs.
+
+<dl>
+    <dt>easy transition</dt>
+    <dd>
+        Changes to the docs inconvenience people as little as possible.
+    </dd>
+    <dt>good UI</dt>
+    <dd>
+        The UI for the docs is aesthetically pleasing, intuitive to use, and gets relevant information with as little friction as possible.
+    </dd>
+</dl>
+
+## Constraints
+
+<dl>
+    <dt>free</dt>
+    <dd>
+        We don't have a budget outside of our own computing power and engineering resources.
+    </dd>
+    <dt>static</dt>
+    <dd>
+        The generated docs should be static files (unless we find a free hosted solution).
+    </dd>
+</dl>
+
+## Solutions
+
+### [Sphinx][sphinx]/[Readthedocs][rtfd]
+
+Sphinx is a mature and complete documentation system written in Python. All documentation hosted by [readthedocs.org][rtfd] uses Sphinx. Sphinx meets all functional requirements of this proposal.
+
+Pros:
+
+- mature and used by many large software projects; many people know it
+- feature-rich: search, referencing, internationalization, templating, generation, plugins, and many others
+
+Cons:
+
+- needs some knowledge of Python
+- needs migration from Markdown to [reStructuredText][rest]
+- needs migration from Crowdin to Sphinx's own [internationalization tools][sphinx_int]
+
+### [Jekyll][jekyll]
+
+Jekyll is a static site generator written in Ruby. It is used to generate the docs of [React.js][react_docs]. It meets some functional requirements of this proposal.
+
+Pros:
+
+- mature and used for many static websites; many people know it
+- integrates well with other tools
+- has powerful templating for the output
+
+Cons:
+
+- does not have search or internationalization
+
+### [JSDoc][jsdoc]
+
+JSDoc is a mature documentation system written in JS. It is used as a back-end to generate automated source code docs for many JS projects. It meets some functional requirements of this proposal.
+
+Pros:
+
+- mature and widely used; many people know it
+- integrates well with other tools
+
+Cons:
+
+- does not have search or internationalization
+
+### [Current System][cordova-docs]
+
+The current Cordova docs could also be extended to meet the proposed requirements.
+
+Pros:
+
+- no migration required
+
+Cons:
+
+- does not have search or templating
+- non-standard, so the learning curve remains
+
+Proposals
+=========
+
+### Option #1: Sphinx
+
+Sphinx (either with readthedocs.org or without) would provide a complete solution for Cordova's documentation needs. However, it would require a (hefty) migration.
+
+### Option #2: Jekyll + JSDoc + Crowdin
+
+A mix of Jekyll, JSDoc, and the current Crowdin pipeline would suit Cordova's documentation needs. The existing documentation can be migrated to such a system with only moderate effort.
+
+Notes
+=====
+
+[This prior analysis][comparison] was used to decide on a JS documentation framework. Currently no quantitative analysis has been made to compare the solution candidates, but one can be carried out if required.
+
+[react_docs]:   https://facebook.github.io/react/docs/getting-started.html
+[unity_docs]:   http://docs.unity3d.com/Manual/index.html
+[ember_docs]:   http://guides.emberjs.com/v1.12.0/
+[angular_docs]: https://docs.angularjs.org/api
+[ionic_docs]:   http://ionicframework.com/docs/
+
+[comparison]:   http://blog.fusioncharts.com/2013/12/jsdoc-vs-yuidoc-vs-doxx-vs-docco-choosing-a-javascript-documentation-generator/
+[sphinx]:       http://sphinx-doc.org/
+[rtfd]:         https://readthedocs.org/
+[rest]:         http://docutils.sourceforge.net/rst.html
+[sphinx_int]:   http://sphinx-doc.org/latest/intl.html
+[jekyll]:       http://jekyllrb.com/
+[jsdoc]:        http://usejsdoc.org/
+[cordova-docs]: https://github.com/apache/cordova-docs
diff --git a/proposals/ThirdPartyPackageManagers.md b/proposals/ThirdPartyPackageManagers.md
index a189575..a4df071 100644
--- a/proposals/ThirdPartyPackageManagers.md
+++ b/proposals/ThirdPartyPackageManagers.md
@@ -22,7 +22,7 @@
 <framework src="path/to/mynu.nuspec" type="nuspec" />
 ```
 
-The above use [existing documented attributes](https://cordova.apache.org/docs/en/5.1.1/plugin_ref/spec.html) for both the <engine> and <framework> tags.
+The above use [existing documented attributes](https://cordova.apache.org/docs/en/5.1.1/plugin_ref/spec.html) for both the `<engine>` and `<framework>` tags.
 
 ## Engine tag
 
diff --git a/proposals/android-n-support.md b/proposals/android-n-support.md
new file mode 100644
index 0000000..90dd47d
--- /dev/null
+++ b/proposals/android-n-support.md
@@ -0,0 +1,46 @@
+# Android N and Cordova

+

+The purpose of this discuss is to highlight the new features of Android N

+that may affect Cordova. I did a brief investigation of the upcoming changes

+and did some minor testing (building a trivial app, running mobilespec, etc).

+I didn't find too many issues, but we should track them as they come up.

+

+You can see a JIRA query for all Android N related issues

+[here][android-n-query]. If you file an issue, be sure to add the "AndroidN"

+label so that it shows up.

+

+

+## Multi-Window Support

+

+This is the big new feature of Android N and one that presents some minor

+problems for existing Cordova apps. When apps that are compiled with the pre-N

+SDK are put into multi-window mode, the user gets a message saying "App may not

+work in multi-window mode". Cordova apps definitely fall into the non-working

+category because they tend to either crash or randomly restart when placed into

+multi-window mode.

+

+The issue is in the way Android handles resizing an app. By default, Android

+just destroys/restarts the current Activity whenever the app changes size.

+Unfortunately, in a Cordova app the webview gets destroyed along with the

+Activity and the app will appear to restart from scratch. In practice, this

+mostly looks like the app randomly restarts sometimes when it's resized. The

+app also sometimes crashes (may be related to the first point

+[here][other-behavior-changes]).

+

+The fix is a really simple one-line change to AndroidManifest.xml and it works

+even with pre-N SDK versions. We just need to make sure that people are aware of

+the issue so that they can either update to newer versions of cordova-android (once

+we've published a fix) or make the change themselves if they're unwilling to update.

+

+I don't think that multi-window support will require any changes to core plugins.

+Some third party plugins that have their own UI might run into issues and may need

+to update, but I haven't done any research. The issue there is that Android assumes

+that any Activity spawned by a multi-window supporting activity also supports

+multi-window, so you could potentially get into a weird state where you add a plugin

+that does not support it and it causes problems. It's something to be aware of.

+Developers can also disable multi-window support by editing AndroidManifest.xml.

+

+

+

+[android-n-query]: https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20labels%20%3D%20AndroidN

+[other-behavior-changes]: http://developer.android.com/preview/behavior-changes.html#other
\ No newline at end of file
diff --git a/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md b/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md
new file mode 100644
index 0000000..16c2d69
--- /dev/null
+++ b/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md
@@ -0,0 +1,190 @@
+The proposal describes the way how we can improve current cordova lib design and interaction between cordova lib and platforms. The document contains high-level descriptions of proposed interfaces only. Fo more details on methods signatures see *.js files in this pull request.
+
+The most important points of this proposal are:
+
+## 1. The PlatformApi class
+
+PlatformApi (or CordovaPlatform) class - an abstraction around particular platform that exposes all the actions for this platform (such as build/run), so they're accessible programmatically. It also knows how to install/uninstall plugins with all source files, web assets and js files, so this is no more responsibility of cordova-lib. It also exposes single 'prepare' method to provide a way for cordova-lib to apply project's settings/www content to platform.
+
+The PlatformApi class needs to be implemented by each platform, that wants to use new API flow. For those platforms, which doesn't provide own PlatformApi, there will be a polyfill in cordova-lib.
+
+There is a PR to cordova-lib, which implements the polyfill: https://github.com/MSOpenTech/cordova-lib/pull/2
+
+### Proposed class structure
+
+#### Constructor
+
+    function PlatformApi() {}
+
+#### Static methods
+
+    PlatformApi.createPlatform = function (cordovaProject, options) {};
+    PlatformApi.updatePlatform = function (cordovaProject, options) {};
+
+These methods are equal to bin/create and bin/update scripts. Installs/updates platform to specified directory and creates a platform project. Accepts a CordovaProject instance, that defines a project structure and configuration, that should be applied to new platform, and an options object.
+
+#### Platform-specific information
+
+    PlatformApi.prototype.getPlatformInfo = function () {};
+
+Gets a CordovaPlatform object, that represents the platform structure:
+Platform's directories/main files locations (config.xml, www, etc.)
+
+#### CLI workflow integration
+
+    PlatformApi.prototype.prepare = function (cordovaProject) {};
+
+Updates installed platform with provided www assets and new app configuration. This method is required for CLI workflow and will be called each time before build, so the changes, made to app configuration and www code, will be applied to platform. 
+
+__NOTE:__ The `prepare` method doesn't rebuild `cordova_plugins` file and doesn't reapply assets and js files, installed by plugins, to platform's www directory. Accepts a `CordovaProject` instance, that defines a project structure and configuration, that should be applied to platform
+
+#### Plugin management
+
+    PlatformApi.prototype.addPlugin = function (plugin, installOptions) {};
+    PlatformApi.prototype.removePlugin = function (plugin) {};
+
+Installs/uninstalls a plugin into platform. These methods handles all the files, shipped by plugin (sources, libs, assets, js-files). Accepts a `PluginInfo` instance that represents plugin that will be installed/uninstalled, and an `options` object.
+
+__NOTE:__ The methods doesn't resolve the dependencies of plugin. Resolving dependencies is still the responsibility of caller.
+
+__NOTE:__ Since `uninstall` method accepts PluginInfo instance as input parameter instead of plugin id, the caller should take care of managing/storing PluginInfo instances for future uninstalls.
+
+##### Platform's 'actions'
+
+    PlatformApi.prototype.build = function(buildOptions) {};
+    PlatformApi.prototype.run = function(runOptions) {};
+    PlatformApi.prototype.clean = function() {};
+    PlatformApi.prototype.requirements = function() {};
+
+These methods are equal to platform's executable scripts. The main difference is that they accepts a structured `options` object instead of array of command line arguments. The `options` structure is highly depends on platform's specific. The detailed list of common options see [PlatformApi reference](PlatformApi.js)
+
+## 2. The ProjectAPI class
+
+ProjectAPI (or CordovaProject) class - an abstraction of cordova project with multiple platforms/plugins installed. Manages the platforms and delegates the responsibilities to corresponding platform:
+
+    Project.run -> this.platforms.foreach(platform.run);
+
+It also does some additional job:
+
+  * fetches plugins/platforms from any sources (git/npm/web)
+  * resolves plugin dependencies
+  * handles platform's restrictions (<engine> tag)
+
+### Proposed class structure
+
+#### Constructor
+
+    function ProjectApi () {}
+
+#### Static methods
+
+    ProjectApi.getProjectAt = function (projectDir) {};
+
+'Static' method, that gets a ProjectApi instance for specified directory. Returns a `ProjectApi` instance.
+
+    ProjectApi.createProject = function (targetDir, appName, appId, options) {};
+
+Initializes an empty cordova project at specified directory. Returns a promise fulfilled with a `ProjectAPI` instance.
+
+#### Project-specific information
+
+    ProjectApi.prototype.getProjectInfo = function () {};
+
+Gets a ProjectInfo structure that describes the project. Similar to `PlatformApi.getPlatformInfo`
+
+#### Platform management
+
+    ProjectApi.prototype.addPlatform = function (platformSpec, options) {};
+
+Adds a new platform to project. Accepts a platform spec that should be one of following:
+
+  - valid platform name: 'android', 'windows', etc.
+  - valid npm identifier, that resolves to valid platform: cordova-android@4.0
+  - git url, that points to repo with valid platform: http://github.com/apache/cordova-android.git#4.0.0
+  - path to local repo of valid platform: /my/cordova/repositories/cordova-android
+
+Does all of the job, related to acquiring the platform code from NPM/git/other sources.
+
+    ProjectApi.prototype.removePlatform = function (platformName, options) {};
+
+Removes a platform from project.
+
+    ProjectApi.prototype.getPlatforms = function () {};
+    ProjectApi.prototype.getPlatform = function (platformName) {};
+
+Gets all/single platform, installed into project. Returns an array of/single `PlatformApi` instance.
+
+#### Plugins management
+
+    ProjectApi.prototype.addPlugin = function (pluginSpec, options) {};
+    ProjectApi.prototype.removePlugin = function (pluginId, options) {};
+
+Adds/removes a plugin into/from project. Also installs/uninstalls it to/from each platform in project. Accepts a plugin spec that should be one of following:
+
+  - valid plugin id that can be resolved through either cordova plugin registry or npm: 'org.apache.cordova.globalization', 'cordova-plugin-globalization'
+  - valid npm identifier, that resolves to valid plugin: `cordova-plugin-globalization@1.0.0`
+  - git url, that points to repo with valid plugin: `http://github.com/apache/cordova-plugin-globalization.git#r1.0.0`
+  - path to local repo of valid plugin: `/my/cordova/repositories/cordova-plugin-globalization`
+
+These methods also responsible for fetching plugin's source from available distribution channels and resolving plugin's dependencies.
+
+    ProjectApi.prototype.getPlugins = function () {};
+    ProjectApi.prototype.getPlugin = function (pluginId) {};
+
+Gets all/single the plugin, installed into project. Returns an array of/single `PluginInfo` instance.
+
+#### Project-platform integration
+
+    ProjectApi.prototype.prepare = function (platform, prepareOptions) {};
+
+'Prepares' a project for building specified platform/platforms. The prepare step is need to be performed to update configuration and www assets for each platform from application's ones before the application will be built. The prepare step isn't required if no configuration changes or www assets changes was made.
+
+#### Project's 'actions'
+
+    ProjectApi.prototype.build = function (platform, buildOptions) {};
+    ProjectApi.prototype.run = function (platform, runOptions) {};
+    ProjectApi.prototype.serve = function (platform, serveOptions) {};
+    ProjectApi.prototype.clean = function(platform, cleanOptions) {};
+    ProjectApi.prototype.requirements = function(platform) {};
+
+These methods works as project-level platform's actions.
+
+    PlatformApi.getPlatform(platform).build(buildOptions)
+
+etc. The `platform` parameter is optional, and if not specified, the command works just as
+
+    PlatformApi.getPlatforms().forEach(function (platform){
+        platform.build(buildOptions);
+    })
+
+For `options` reference see [ProjectAPI](ProjectApi.js)
+
+## `cordova-common` module
+
+'cordova-common' module - required to share similar code between platforms and lib. Currently there are following candidates for moving to `cordova-common`:
+
+    `superspawn`
+    `ActionStack`
+    `CordovaError`
+    `PlatformJson`
+    `ConfigParser`
+    `PluginInfo`
+    `PluginInfoProvider`
+    `ConfigChanges`
+    `ConfigKeeper`
+    `ConfigFile`
+    `mungeUtil`
+    `xmlHelpers`
+
+The PR for `cordova-common` module is ready and published here: https://github.com/MSOpenTech/cordova-lib/pull/3.
+
+## Links:
+PlatformApi proposal with APIs' definitions: https://github.com/cordova/cordova-discuss/pull/9
+PlatformApi polyfill implementation for cordova-lib: https://github.com/MSOpenTech/cordova-lib/pull/2
+`cordova-common` implementation: https://github.com/MSOpenTech/cordova-lib/pull/3
+
+Pull requests:
+
+- `PlatformApi` polyfill: https://github.com/MSOpenTech/cordova-lib/pull/2
+- `cordova-common` implementation: https://github.com/MSOpenTech/cordova-lib/pull/3
+
diff --git a/proposals/cordova-lib refactoring/CordovaPlatform.js b/proposals/cordova-lib refactoring/CordovaPlatform.js
new file mode 100644
index 0000000..4d23414
--- /dev/null
+++ b/proposals/cordova-lib refactoring/CordovaPlatform.js
@@ -0,0 +1,56 @@
+/* jshint node:true, unused:false */
+
+var path = require('path');
+var BuildConfig = require('cordova-common').BuildConfig;
+var ConfigParser = require('cordova-common').ConfigParser;
+
+/**
+ * Encapsulates and stores platform's information.
+ *
+ * @class
+ */
+function CordovaPlatform(root) {
+    /**
+     * Simple object that exposes platform's filesystem locations, such as www
+     *   directory.
+     *
+     * @type  {Object}
+     */
+    this.locations = {
+        /** @type {String} Platform's www directory location */
+        www: path.join(root, 'www'),
+        /** @type {String} Platform's config.xml file location  */
+        configXml: path.join(root, 'config.xml'),
+        /**
+         * Location of cordova.js that shipped with platform.
+         *   NOTE: THIS PATH IS NOT ABSOLUTE. IT IS RELATIVE TO PLATFORM'S
+         *   ORIGINAL PACKAGE DIRECTORY, NOT THE INSTALLED PLATFORM'S LOCATION.
+         *
+         * @type  {String}
+         */
+        cordovaJs: path.join('bin', 'template', 'www', 'cordova.js'),
+        /**
+         * Location of platform's cordova.js sources, shipped with platform.
+         *   NOTE: THIS PATH IS NOT ABSOLUTE. IT IS RELATIVE TO PLATFORM'S
+         *   ORIGINAL PACKAGE DIRECTORY, NOT THE INSTALLED PLATFORM'S LOCATION.
+         *
+         * @type  {String}
+         */
+        cordovaJsSrc: 'cordova-js-src'
+    };
+
+    /**
+     * The installed platform's root location.
+     *
+     * @type {String}
+     */
+    this.root = root;
+
+    /**
+     * Represents the platform's design-time and runtime configuration which
+     *   stored in config.xml file.
+     *
+     * @type  {ConfigParser}
+     */
+    this.projectConfig = new ConfigParser(this.locations.configXml);
+}
diff --git a/proposals/cordova-lib refactoring/CordovaProject.js b/proposals/cordova-lib refactoring/CordovaProject.js
new file mode 100644
index 0000000..56c0dcd
--- /dev/null
+++ b/proposals/cordova-lib refactoring/CordovaProject.js
@@ -0,0 +1,53 @@
+/* jshint node:true, unused:false */
+
+var path = require('path');
+var BuildConfig = require('cordova-common').BuildConfig;
+var ConfigParser = require('cordova-common').ConfigParser;
+
+/**
+ * Encapsulates and stores project information.
+ *
+ * @class
+ */
+function CordovaProject(root) {
+    /**
+     * Simple object that exposes this project's filesystem locations, such as www
+     *   directory.
+     *
+     * @type  {Object}
+     */
+    this.locations = {
+        /** @type {String} Www directory location */
+        www: path.join(root, 'www'),
+        /** @type {String} config.xml file location  */
+        configXml: path.join(root, 'config.xml'),
+        /** @type {String} Installed platforms location */
+        platforms: path.join(root, 'platforms'),
+        /** @type {String} Installed plugins location */
+        plugins: path.join(root, 'plugins')
+    };
+
+    /**
+     * The project's root location.
+     *
+     * @type {String}
+     */
+    this.root = root;
+
+    /**
+     * Represents the configuration, used for building project. Populated with
+     *   values from build.json, if exists, or with some default values,
+     *   if not.
+     *
+     * @type {BuildConfig}
+     */
+    this.buildConfig = new BuildConfig(root);
+
+    /**
+     * Represents the project design-time and runtime configuration which stored in
+     *   project's config.xml file.
+     *
+     * @type  {ConfigParser}
+     */
+    this.projectConfig = new ConfigParser(this.locations.configXml);
+}
diff --git a/proposals/cordova-lib refactoring/PlatformApi.js b/proposals/cordova-lib refactoring/PlatformApi.js
new file mode 100644
index 0000000..cbbb724
--- /dev/null
+++ b/proposals/cordova-lib refactoring/PlatformApi.js
@@ -0,0 +1,201 @@
+
+/*jshint node:true, unused:false */
+
+var ConfigParser  = require('cordova-common').ConfigParser;
+var PluginInfo  = require('cordova-common').PluginInfo;
+var Requirement  = require('cordova-common').Requirement;
+
+/**
+ * Class, that acts as abstraction over particular platform. Encapsulates the
+ *   platform's properties and methods.
+ *
+ * Platform that implements own PlatformApi instance _should implement all
+ *   prototype methods_ of this class to be fully compatible with cordova-lib.
+ *
+ * The PlatformApi instance also should define the following field:
+ *
+ * * platform: String that defines a platform name.
+ */
+function PlatformApi() {}
+
+/**
+ * Installs platform to specified directory and creates a platform project.
+ *
+ * @param  {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to new platform
+ *   (contains platform's target location and ConfigParser instance for
+ *   project's config). This argument is optional and if not defined, this means
+ *   that platform is used as standalone project and is not a part of cordova
+ *   project.
+ * @param  {Object}  options  An options object. The most common options are:
+ * @param  {String}  options.customTemplate  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  options.link  Flag that indicates that platform's sources
+ *   will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+PlatformApi.createPlatform = function (cordovaProject, options) {};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param   {CordovaProject}  cordovaProject  A CordovaProject instance, that
+ *   defines a project structure and configuration, that should be applied to
+ *   new platform (contains platform's target location and ConfigParser instance
+ *   for project's config). This argument is optional and if not defined, this
+ *   means that platform is used as standalone project and is not a part of
+ *   cordova project.
+ * @param  {Object}  options  An options object. The most common options are:
+ * @param  {String}  options.customTemplate  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  options.link  Flag that indicates that platform's sources
+ *   will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+PlatformApi.updatePlatform = function (cordovaProject, options) {};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return  {CordovaPlatform}  A structure that contains the description of
+ *   platform's file structure and other properties of platform.
+ */
+PlatformApi.prototype.getPlatformInfo = function () {};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ *   configuration. This method is required for CLI workflow and will be called
+ *   each time before build, so the changes, made to app configuration and www
+ *   code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to platform
+ *   (contains project's www location and ConfigParser instance for project's
+ *   config).
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.prepare = function (cordovaProject) {};
+
+/**
+ * Installs a new plugin into platform. This method only copies non-www files
+ *   (sources, libs, etc.) to platform. It also doesn't resolves the
+ *   dependencies of plugin. Both of handling of www files, such as assets and
+ *   js-files and resolving dependencies are the responsibility of caller.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  installOptions  An options object. Possible options below:
+ * @param  {Boolean}  installOptions.link: Flag that specifies that plugin
+ *   sources will be symlinked to app's directory instead of copying (if
+ *   possible).
+ * @param  {Object}  installOptions.variables  An object that represents
+ *   variables that will be used to install plugin. See more details on plugin
+ *   variables in documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.addPlugin = function (plugin, installOptions) {};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ *   id, caller shoud take care of managing/storing PluginInfo instances for
+ *   future uninstalls.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.removePlugin = function (plugin) {};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param  {Object}  buildOptions  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return {Promise<Object[]>} A promise either fulfilled with an array of build
+ *   artifacts (application packages) if package was built successfully,
+ *   or rejected with CordovaError. The resultant build artifact objects is not
+ *   strictly typed and may conatin arbitrary set of fields as in sample below.
+ *
+ * ```
+ * {
+ *   architecture: 'x86',
+ *   buildType: 'debug',
+ *   path: '/path/to/build',
+ *   type: 'app'
+ * }
+ * ```
+ *
+ * The return value in most cases will contain only one item but in some cases
+ *   there could be multiple items in output array, e.g. when multiple
+ *   arhcitectures is specified.
+ */
+PlatformApi.prototype.build = function(buildOptions) {};
+
+/**
+ * Builds an application package for current platform and runs it on
+ *   specified/default device. If no 'device'/'emulator'/'target' options are
+ *   specified, then tries to run app on default device if connected, otherwise
+ *   runs the app on emulator.
+ *
+ * @param   {Object}  runOptions  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ *   successfully, or rejected with CordovaError.
+ */
+PlatformApi.prototype.run = function(runOptions) {};
+
+/**
+ * Cleans out the build artifacts from platform's directory.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError.
+ */
+PlatformApi.prototype.clean = function() {};
+
+/**
+ * Performs a requirements check for current platform. Each platform defines its
+ *   own set of requirements, which should be resolved before platform can be
+ *   built successfully.
+ *
+ * @return  {Promise<Requirement[]>}  Promise, resolved with set of Requirement
+ *   objects for current platform.
+ */
+PlatformApi.prototype.requirements = function() {};
diff --git a/proposals/cordova-lib refactoring/ProjectApi.js b/proposals/cordova-lib refactoring/ProjectApi.js
new file mode 100644
index 0000000..06a1f65
--- /dev/null
+++ b/proposals/cordova-lib refactoring/ProjectApi.js
@@ -0,0 +1,281 @@
+
+/*jshint node:true, unused:false */
+
+/**
+ * @class Class, that acts as abstract on top of Cordova project. Encapsulates the
+ *   basic properties, that represents project configuration and methods for
+ *   managing the project.
+ */
+function ProjectApi () {}
+
+/**
+ * Gets a ProjectApi instance for specified directory.
+ *
+ * @param   {String}  projectDir  Path to cordova project.
+ *
+ * @return  {Promise<ProjectApi>}  Returns a promise either fulfilled with a
+ *   Cordova project instance or rejected with CordovaError.
+ */
+ProjectApi.getProjectAt = function (projectDir) {};
+
+/**
+ * Initializes an empty cordova project at specified directory. Copies
+ *
+ * @param  {String} targetDir Path to directory, where new project will be
+ *   created.
+ * @param  {String} [appName = 'HelloCordova']   Application name, that will be
+ *   used for '<name>' element in config.xml. If not specified, 'HelloCordova'
+ *   will be used.
+ * @param  {String} [appId = 'io.cordova.hellocordova']     Application id in
+ *   form of reverse domain style identifier, that will be used for 'id'
+ *   attribute of '<widget>' element. If not specified 'io.cordova.hellocordova'
+ *   will be used.
+ * @param  {Object} [options]   An options object. The most common options are:
+ * @param  {String} options.wwwSource  Specifies the www assets source for new
+ *   application instead of default one. If not specified, the Cordova
+ *   HelloWorld assets will be used.
+ * @param  {Boolean}  options.link  Specifies that www source will be symlinked
+ *   to app's directory instead of copying.
+ *
+ * @return {Promise<ProjectApi>} Returns a promise either fulfilled with a
+ *   Cordova project instance or rejected with CordovaError.
+ */
+ProjectApi.createProject = function (targetDir, appName, appId, options) {};
+
+/**
+ * Gets a ProjectInfo structure that describes the project.
+ *
+ * @return  {CordovaProject}  A CordovaProject object.
+ */
+ProjectApi.prototype.getProjectInfo = function () {};
+
+/**
+ * Adds a new platform to project.
+ *
+ * @param  {String}  platformSpec  A platform spec that should be one of
+ *   following:
+ *
+ * - valid platform name: 'android', 'windows', etc.
+ * - valid npm identifier, that resolves to valid platform: cordova-android@4.0
+ * - git url, that points to repo with valid platform:
+ *       http://github.com/apache/cordova-android.git#4.0.0
+ * - path to local repo of valid platform:
+ *     /my/cordova/repositories/cordova-android
+ *
+ * @param {Object}  [options] The options object. Supported properties:
+ * @param {Boolean} [options.saveToProject = false]  Flag that indicates, that added platform
+ *   should be saved into project configuration to be easily restored after. The
+ *   approach is similar to 'npm install --save' command.
+ *
+ * @return {Promise} A promise either fulfilled if platform is installed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.addPlatform = function (platformSpec, options) {};
+
+/**
+ * Removes a platform from project.
+ *
+ * @param  {String}  platformName  A name of platform that should be removed
+ *   from project.
+ * @param {Object}   [options] The options object. Supported properties:
+ * @param {Boolean}  [options.saveToProject = false]  Flag that indicates, that
+ *   platform also should be removed from project configuration.
+ *
+ * @return {Promise} A promise either fulfilled if platform is removed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.removePlatform = function (platformName, options) {};
+
+/**
+ * Adds a new plugin into project. Installs it to each platform in project.
+ *
+ * @param  {String}  pluginSpec  A plugin spec that should be one of following:
+ *
+ *   - valid plugin id that can be resolved through either cordova
+ *   plugin registry or npm:
+ *       'org.apache.cordova.globalization', 'cordova-plugin-globalization'
+ *   - valid npm identifier, that resolves to valid plugin:
+ *       cordova-plugin-globalization@1.0.0
+ *   - git url, that points to repo with valid plugin:
+ *       http://github.com/apache/cordova-plugin-globalization.git#r1.0.0
+ *   - path to local repo of valid plugin:
+ *       /my/cordova/repositories/cordova-plugin-globalization
+ *
+ * @param  {Object}  [options]    An options object. Possible options are:
+ * @param  {Boolean} saveToProject Flag that indicates, that added plugin should
+ *   be saved into project configuration.
+ * @param  {Boolean} link       Flag that specifies that plugin sources will be
+ *   symlinked to app's directory instead of copying if possible.
+ * @param  {String}  searchPath Valid path, that will be used to search for
+ *   plugin in local filesystem.
+ * @param  {Object}  variables  An object that represents variables that will be
+ *   used to install plugin. See more details on plugin variables in
+ *   documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return {Promise} A promise either fulfilled if plugin is installed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.addPlugin = function (pluginSpec, options) {};
+
+/**
+ * Removes a plugin from project.
+ *
+ * @param  {String}  pluginId  An id of plugin that should be removed from
+ *   project.
+ * @param {Object} [options] The options object. Supported properties:
+ * @param {Boolean}  options.saveToProject  Flag that indicates, that plugin
+ *   also should be removed from project configuration.
+ *
+ * @return {Promise} A promise either fulfilled if platform is removed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.removePlugin = function (pluginId, options) {};
+
+/**
+ * Gets all platforms, installed into project.
+ *
+ * @return  {PlatformApi[]}  An array of PlatformApi instances.
+ */
+ProjectApi.prototype.getPlatforms = function () {};
+
+/**
+ * Gets a platform by name
+ *
+ * @param   {String}  platformName  The platform name.
+ *
+ * @return  {PlatformApi}  PlatformApi instance for specified platform.
+ */
+ProjectApi.prototype.getPlatform = function (platformName) {};
+
+/**
+ * Gets all the plugins, installed into project.
+ *
+ * @return  {Array<PluginInfo>}  An array of PluginInfo instances.
+ */
+ProjectApi.prototype.getPlugins = function () {};
+
+/**
+ * Gets plugins, specified by id.
+ *
+ * @return  {PluginInfo}  A PluginInfo instance for specified plugin.
+ */
+ProjectApi.prototype.getPlugin = function (pluginId) {};
+
+/**
+ * Prepares a project for building specified platform/platforms. The prepare
+ *   step is need to be performed to update configuration and www assets for
+ *   each platform from application's ones before the application will be built.
+ *   The prepare step isn't required if no configuration changes or www assets
+ *   changes was made.
+ *
+ * @param   {String|String[]}  [platform]  Single platform or array of platform
+ *   names, that needs to be prepared. If omitted, all platform, added to
+ *   project will be prepared.
+ * @param   {Object}  [prepareOptions]  An options object with following fields:
+ * @param   {Boolean} prepareOptions.browserify Specifies that project should be
+ *   prepared with 'browserify' flow to embed all plugins' JS files and cordova
+ *   JS sources into one single file.
+ *
+ * @return  {Promise}  A promise either fulfilled, if platform/platforms
+ *   prepared successfully, or rejected with CordovaError otherwise.
+ */
+ProjectApi.prototype.prepare = function (platform, prepareOptions) {};
+
+/**
+ * Builds an application package for specified platform/platforms.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single name.
+ *   If not specified, builds packages for all platforms, installed into
+ *   project.
+ *
+ * @param  {Object}  [buildOptions]  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return {Promise<Object>} A promise either fulfilled with an array of build
+ *   artifacts for each platform, if package was built successfully, or rejected
+ *   with CordovaError. The keys of resultant object is a platform names, and
+ *   values - arrays of build artifact objects. The structure of build artifacts
+ *   is descriped in PlatformApi reference.
+ */
+ProjectApi.prototype.build = function (platform, buildOptions) {};
+
+/**
+ * Builds and runs an application package for specified platform on specified
+ *   device/emulator.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single name.
+ *   If omitted, method runs packages for all platforms, installed into project.
+ * @param   {Object}  [runOptions]  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if application ran successfully,
+ *   or rejected with CordovaError.
+ */
+ProjectApi.prototype.run = function (platform, runOptions) {};
+
+/**
+ * Runs an application on a local web-server and launches a browser to display
+ *   application content.
+ *
+ * @param   {String}  [platform]      A platform to run server for.
+ * @param   {Object}  [serveOptions]  A set of options to pass to serve command.
+ *   Available options are:
+ * @param   {Number}  serveOptions.port  A port to bind server to.
+ * @param   {String}  serveOptions.target  A browser name. Available targets
+ *   depends on platform. Most common are: 'chrome', 'safari', 'opera', 'firefox'.s
+ *
+ * @return  {Promise}  A promise either fulfilled, if server ran successfully,
+ *   or rejected with CordovaError otherwise.
+ */
+ProjectApi.prototype.serve = function (platform, serveOptions) {};
+
+/**
+ * Cleans out the build artifacts for specified platform.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single
+ *   platform, which needs to be cleaned. If not specified, run clean for all
+ *   platforms, installed into project.
+ * @param   {Object}  [cleanOptions]  An options object. The structure is not
+ *   defined explicitly, so it can be used to pass some platfom specific vaues
+ *   to platform.
+ *
+ * @return {Promise} A promise either fulfilled or rejected with CordovaError.
+ */
+ProjectApi.prototype.clean = function(platform, cleanOptions) {};
+
+/**
+ * Performs a requirements check for each platforms installed. Each platform
+ *   defines its own set of requirements, which should be resolved before
+ *   platform can be built successfully.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single
+ *   platform, which requirements needs to be checked for.
+ *
+ * @return  {Promise<Requirement[]>}  Promise resolved with set of Requirement
+ *   objects for each platform.
+ */
+ProjectApi.prototype.requirements = function(platform) {};
diff --git a/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-current.png b/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-current.png
new file mode 100644
index 0000000..df0954d
--- /dev/null
+++ b/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-current.png
Binary files differ
diff --git a/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-proposed.png b/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-proposed.png
new file mode 100644
index 0000000..cab0cec
--- /dev/null
+++ b/proposals/images/ios-whitelist-removal/cordova-ios-4-whitelist-proposed.png
Binary files differ
diff --git a/proposals/ios-whitelist-removal.md b/proposals/ios-whitelist-removal.md
new file mode 100644
index 0000000..dc344d5
--- /dev/null
+++ b/proposals/ios-whitelist-removal.md
@@ -0,0 +1,37 @@
+# Proposal to Remove the Cordova iOS Native Whitelist
+
+This proposal is to advocate for the removal of the usage of the cordova-plugin-whitelist plugin in cordova-ios-4.x.
+
+In the diagrams, CSP refers to [Content-Security Policy](https://developer.mozilla.org/en-US/docs/Web/Security/CSP) and ATS refers to [App Transport Security](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33).
+These two components are built-in to iOS, and are not part of Apache Cordova.
+
+The native whitelist component pictured is Apache Cordova's [cordova-plugin-whitelist](https://github.com/apache/cordova-plugin-whitelist) which is new for cordova-ios-4x.
+
+## Current Whitelist System
+
+![current cordova-ios-4 whitelist](images/ios-whitelist-removal/cordova-ios-4-whitelist-current.png)
+
+All connections in the WebView *must* be whitelisted in the `CSP` *and* also be whitelisted in native through the `<access>` tag in `config.xml`. In the last released version of the `cordova-cli`, all `<access>` tags are automatically converted to `ATS` directives in the app's `Info.plist` file. 
+
+There is a deficiency in `cordova-plugin-whitelist` in that `WKWebView` connections are not whitelisted while on iOS 8 (because WKWebView connections cannot be intercepted using NSURLProtocol). On iOS 9, `WKWebView` connections are whitelisted and intercepted by ATS.
+
+There is one difference in whitelisting through `ATS` and cordova-plugin-whitelist: a wildcard `*` in `cordova-plugin-whitelist` means all connections are accepted, while in `ATS` it means the same except that you can also restrict certain domains to connect through https or a certain TLS version, for example.
+
+The way `cordova-plugin-whitelist` works is by [implementing a protocol](https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVURLRequestFilter.h) -- in the platform *all* plugins are then iterated through, and checked whether they implement a protocol method, and [each plugin is asked](https://github.com/apache/cordova-ios/blob/0ec2949d9b37495da6504867bfb371bd868242f0/CordovaLib/Classes/Public/CDVViewController.m#L518) whether a request is to be allowed. This means that any plugin that implements the protocol method can *veto* a request.
+
+It seems that this code was added to provide a generic way to allow whitelist as a plugin -- the utility of these protocol methods for other uses are not apparent.
+
+## Proposed Whitelist System
+
+![proposed cordova-ios-4 whitelist](images/ios-whitelist-removal/cordova-ios-4-whitelist-proposed.png)
+
+The proposed whitelist system here requires us to remove:
+
+1. The [iteration of plugins](https://github.com/apache/cordova-ios/blob/0ec2949d9b37495da6504867bfb371bd868242f0/CordovaLib/Classes/Public/CDVViewController.m#L518) to see if they conform to the [protocol methods](https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVURLRequestFilter.h)
+2. Usage of the [cordova-plugin-whitelist](https://github.com/apache/cordova-plugin-whitelist) itself
+
+This simplifies things in that we rely solely on iOS to handle security functionality -- Apple is a far better expert than us to handle these things.
+
+Developers still have to specify `<access>` tags to whitelist domains when they are whitelisted to in the `CSP` however, but this only applies to `iOS 9` and above. `<access>` tags are converted to `ATS` directives in the app's `Info.plist` by the `cordova-cli` and this functionality is only applicable for `iOS 9` and above. For `iOS 8` and below, the `<access>` tags have no effect. Thus, the adoption of this proposal basically removes all whitelist functionality for iOS versions 8 and below.
+
+An automatic `CSP to <access> tag` parser was proposed (through `cordova-lib` ios parser) -- this could work but at an expense of backwards-compatibility.
\ No newline at end of file
diff --git a/proposals/pinningAndVersioning.md b/proposals/pinningAndVersioning.md
new file mode 100644
index 0000000..b45416d
--- /dev/null
+++ b/proposals/pinningAndVersioning.md
@@ -0,0 +1,40 @@
+# Pinning and Versioning
+
+## Pinning Plugins
+
+We want to start pinning core plugins to `cordova-lib`. When a user using the `cordova-cli` runs the command `cordova plugin add cordova-plugin-device`, the version that is pinned in `cordova-lib` should be fetched from **npm** instead of fetching the `latest` tag.
+
+This assumes:
+* user has not specified a version during add step. (`cordova plugin add cordova-plugin-file@2.0.0`)
+* user does not  have a version specified in `config.xml`. (`<plugin name="cordova-plugin-device" spec="2.0.0" />`)
+
+The user specified version will always trump the pinned `cordova-lib` plugin version.
+
+I plan on pinning the plugins in the `package.json` of `cordova-lib`.
+
+    'cordovaPlugins' : {
+    'cordova-plugin-file':'~3.0.0',
+    'cordova-plugin-device':'~1.0.0'
+    }
+
+I suggest using the same pinning strategy as we currently do for platforms. `~1.0.0` would grab version `1.0.0` or the highest `patch` releases. It is essentially equivalent to `1.0.x`.These pinned versions should be reviewed and updated with each release of `cordova-cli` and `cordova-lib`.
+
+## Why Pin?
+
+Cordova needs to do a better job at stability. 
+
+Currently, `cordova-cli` fetches the `latest` plugins from **npm**. When we release major updates for plugins, they may require newer versions of platforms and tools. When this happens, developers using older versions of platforms and tools will start to see `engine` tag failures when attempting to install the `latest` plugins. They will have to explicitly install older versions by running `cordova plugin add cordova-plugin-file@2.0.0`. This is useable but not ideal. Users will most likely get confused when they first see the `engine` failures.
+
+## Versioning
+
+Each `cordova` version (`cordova-cli/cordova-lib`) will now always have pinned plugins and platforms. We will only tell users to update their tools and advise against updating platforms and plugins independently (unless they want to live on the edge or need those bug fixes asap). This `cordova` version will be the outwards facing version users will see. 
+
+`cordova` will still follow `SemVer`. Now, a `major` platform bump will be considered a `major` version bump for `cordova`. This will lead to a higher frequency of `major` `cordova` releases. We will try to mitigate this by trying to get platforms to release `major` updates around similar timelines, but this won't always be the case. 
+
+Plugin version updates will be handled on a case by case basis. Most plugin updates will only require a `minor` update to `cordova`.
+
+## Updating
+
+Hopefully these new strategies will allow us to offer an improved updating workflow. The goal would be to have a `cordova update` command which would update the projects platforms and plugins based on what is pinned in `cordova`. A user would just have update their version of `cordova` and run the `cordova update` command on their project to be using the most up to date version of `cordova` in their projects. 
+
+Also, part of the updating workflow would be to better support `cordova platform/plugin check` and `cordova outdated` to see which plugins and platforms can be updated. 
diff --git a/proposals/plugin-version-fetching.md b/proposals/plugin-version-fetching.md
new file mode 100644
index 0000000..4916e03
--- /dev/null
+++ b/proposals/plugin-version-fetching.md
@@ -0,0 +1,130 @@
+# Plugin Version Fetching Proposal

+

+## Overview

+

+This is a proposal to improve the way we fetch plugins from npm. There is a need for us to do something beyond pinning plugin versions in cordova-lib as that does not support third party plugins. If we are solving this problem in Cordova, we can do so in a general way that improves the stability of the entire ecosystem and not just core. This proposal suggests that we add support for a mapping of plugin versions to project requirements in the plugin package.json that the CLI can check against. This would replace the current `<engine>` tag in the plugin.xml.

+

+The reason we insert this into the package.json is that it is possible to get a package.json from npm without fetching the whole package (`npm info <plugin-package-name>`), thus preventing the need to fetch all the versions of a plugin to find a compatible version. This way the pinning information can live in the npm package rather than a centralized location like cordova-lib.

+

+### Proposal

+

+I propose we add this entry to the "cordova" key in the package.json for plugins:

+

+```

+cordovaDependencies:

+{

+    <plugin-version>:

+    {

+        <constraint>: <constraint-version>,

+        ...,

+

+    },

+    ...

+}

+```

+

+#### `<plugin-version>` allowed values

+* Single version (e.g. `1.0.0`)

+* Upper Bound (e.g. `<2.0.0`). This is for BIG breaking changes. For example, if we made a change to some platform that breaks compatibility with all earlier versions of a plugin, we would use this tag to retroactively update their mappings. It won't override earlier tags, just add to them. See [3] for a clarification of this behavior. This is sugar; we could leave it out if we want to keep things simple

+

+#### `<constraint>` allowed values:

+* `cordova`

+* Platforms (e.g. `cordova-android`)

+* Plugins (e.g. `cordova-plugin-camera`)

+

+

+#### `<constraint-version>` syntax:

+* npm semver

+

+Essentially, this compiles the plugin.xml `<engine>` tags for each version of a plugin into one handy list in package.json. Each entry in the object needs to only specify the platform versions it cares about, just like the engine tag. We can also add support for plugin dependency versions (as in the plugin.xml's `<dependency>` tag).

+

+When the user runs `cordova plugin add <plugin-package-name>`, the CLI will check the plugin versions in descending order to examine each constraint entry and determine if the current project can support that plugin version. It will then try and fetch the highest compatible plugin version (see [1] and [2] for high level pseudocode). The CLI must clearly indicate why the user is not getting the latest version of a plugin if it is not compatible with the current project. This can take the form of listing the project requirements for the latest plugin version in some human readable way.

+

+If a plugin version's project requirements information is not specified, the CLI will use the project requirements information for the next version down. For example, consider the following entry:

+

+```

+cordovaDependencies: {

+    "0.0.1": { ... },

+    "1.0.0": { ... }

+}

+```

+

+Here, we have specified the project requirements of two versions of a plugin (0.0.1 and 1.0.0). All versions of the plugin between 0.0.1 and 1.0.0 are assumed to have the requirements as those specified in the 0.0.1 entry. If the current project satisfies the 0.0.1 project requirements, then we get the highest version of the plugin that is greater than or equal to 0.0.1 and less than 1.0.0. This helps us to reduce the size of the mapping if the project requirements don't change across multiple releases.

+

+Fetching should always fall back to the current behavior (fetching latest/pinned plugin versions) if there are no versions of the plugin that the project supports. This is to make sure that if some plugin developer neglects their plugin mapping, their plugin does not become impossible to install without giving a specific version. However, in this case the CLI will deliver a stern warning that the project might not build and explain what project requirements were not satisfied.

+

+### Generating the mapping

+

+We can include a script in plugman to generate the mapping based on old `<engine>` tags in a git repo to make it easier for other developers to opt in. For future releases, the mapping will have to be updated as part of the release step. This should mostly involve us staying up to date with the `<engine>` tag information like we have in the past and updating older versions if there were breaking changes in the platform (with a new upper bound).

+

+While the cordova CLI version can be used as a constraint in the mapping, we should probably default to using platform constraints instead whenever possible. My reasoning here is that it is too easy for the CLI version to go out of sync with a project's installed platforms/plugins. Still, after discussing this with others offline it was made clear to me that it should be available as a constraint because it is more likely that third party plugin developers test against a CLI version rather than individual platforms.

+

+## Pros

+

+* Works for third party and core plugins

+* Keeps plugin platform dependencies in the plugin

+* Allows for more nuanced plugin fetching than pinning does (project's platform versions will be taken into account)

+

+## Cons

+

+* We need to be vigilant in generating this mapping and maintaining plugin.xml when making releases

+

+## Footnotes

+

+#### [1] Plugin Fetching behavior for `cordova plugin add`

+```

+If version is specified by user (i.e. '@'):

+    Fetch that version

+Else if version is specified in config.xml:

+    Fetch that version

+Else:

+    If Cordova dependency constraint mappings are found in plugin's package.json:

+        If some plugin version's constraint mapping is satisfied by current project:

+            Let x = plugin version of highest mapping that is satisfied

+            Let y = plugin version of the next mapping above x (an unsatisfied mapping)

+

+            Fetch highest version of plugin that is >= x and < y

+            Print brief explanation as to why that version was fetched

+        Else:

+            Fetch latest (or pinned) version of plugin

+            Warn user that the project might not build

+    Else:

+        Fetch latest (or pinned) version of plugin (i.e. the current behavior)

+```

+

+##### [2] Logic for determining if a plugin version's constraint mapping is satisfied

+```

+First, AND together all applicable upper range constraints for this plugin version's constraint mapping (see [3])

+

+If Cordova version is constrained and installed version does not satisfy semver constraint:

+    return NotSatisfied

+Else:

+    For each platform/plugin in constraint mapping:

+        If that platform/plugin is installed in project:

+            If project's installed platform/plugin version satisfies the mapped semver constraint:

+                Continue

+            Else:

+                Return NotSatisfied

+        Else:

+            Continue

+

+    Return Satisfied

+```

+

+#### [3] Example for Upper Bound Logic

+

+Consider this mapping:

+

+```

+cordovaDependencies: {

+    "0.0.1": { cordova-ios: ">1.0.0" },

+    "<1.0.0": { cordova-ios: "<2.0.0" },

+    "<2.0.0": { cordova-ios: "<5.0.0" }

+}

+```

+

+Here we specify one plugin version (0.0.1) and two upper bounds (<1.0.0 and <2.0.0) that constrain cordova-ios. The two upper bounds do not override the constraint of 0.0.1, they are combined via AND at evaluation time. When we go to check the cordova-ios version of the project, the constraint we will evaluate for plugin version 0.0.1 will be the combination of these three:

+

+```

+    >1.0.0 AND <2.0.0 AND <5.0.0

+```