diff --git a/resources/static/dialog/resources/channel.js b/resources/static/dialog/resources/channel.js
index 2353280621ae29b22eba36facf94db4c1db2f6d5..99dd6d836630eb04dde0d573a6b696f4ba87672e 100644
--- a/resources/static/dialog/resources/channel.js
+++ b/resources/static/dialog/resources/channel.js
@@ -55,6 +55,7 @@
   var win = window,
       nav = navigator,
       onCompleteCallback,
+      _relayName,
       _relayWindow = null;
 
   function getRelayName() {
@@ -67,8 +68,9 @@
   }
 
   function getRelayWindow() {
-    if (!_relayWindow)
-      _relayWindow = win.opener.frames[getRelayName()];
+    if (!_relayWindow) {
+      _relayWindow = win.opener.frames[_relayName];
+    }
     return _relayWindow;
   }
 
@@ -80,28 +82,34 @@
     // TODO - Add a check for whether the dialog was opened by another window
     // (has window.opener) as well as whether the relay function exists.
     // If these conditions are not met, then print an appropriate message.
-
-    var REGISTERED_METHODS = {
-      'get': function(origin, params, onsuccess, onerror) {
-        // check for old controller methods
-        // FIXME KILL THIS SOON
-        if (controller.get) {
-          return controller.get(origin, params, onsuccess, onerror);          
-        } else {
-          return controller.getVerifiedEmail(origin, onsuccess, onerror);
+    _relayName = getRelayName();
+    if(_relayName !== "NATIVE") {
+      var REGISTERED_METHODS = {
+        'get': function(origin, params, onsuccess, onerror) {
+          // check for old controller methods
+          // FIXME KILL THIS SOON
+          if (controller.get) {
+            return controller.get(origin, params, onsuccess, onerror);
+          } else {
+            return controller.getVerifiedEmail(origin, onsuccess, onerror);
+          }
         }
+      };
+
+      // The relay frame will give us the origin and a function to call when
+      // dialog processing is complete.
+      var frameWindow = getRelayWindow();
+
+      if (frameWindow) {
+        frameWindow.BrowserID.Relay.registerClient(REGISTERED_METHODS);
+      }
+      else {
+        // Only run if we are searching for the IFRAME.  If the relay name is
+        // NATIVE, that means that either the channel has already been set up
+        // before this or it will be set up after this.  Since the relay name is
+        // native, do not throw an exception.
+        throw "relay frame not found";
       }
-    };
-    
-    // The relay frame will give us the origin and a function to call when 
-    // dialog processing is complete.
-    var frameWindow = getRelayWindow();
-    
-    if (frameWindow) {
-      frameWindow.BrowserID.Relay.registerClient(REGISTERED_METHODS);
-    }
-    else {
-      throw "relay frame not found";
     }
   }
 
@@ -114,14 +122,14 @@
 
   function close() {
     var frameWindow = getRelayWindow();
-    
+
     if (frameWindow) {
       frameWindow.BrowserID.Relay.unregisterClient();
       _relayWindow = null;
     }
     else {
       throw "relay frame not found";
-    }    
+    }
   }
 
   function init(options) {
@@ -140,7 +148,7 @@
   if(window.BrowserID) {
     BrowserID.Channel = {
       /**
-       * Used to intialize the channel, mostly for unit testing to override 
+       * Used to intialize the channel, mostly for unit testing to override
        * window and navigator.
        * @method init
        */
@@ -148,7 +156,7 @@
 
       /**
        * Open the channel.
-       * @method open 
+       * @method open
        * @param {object} options - contains:
        * *   options.getVerifiedEmail {function} - function to /get
        */
@@ -162,7 +170,7 @@
   }
 
   /**
-   * This is here as a legacy API for addons/etc that are depending on 
+   * This is here as a legacy API for addons/etc that are depending on
    * window.setupChannel;
    */
   window.setupChannel = open;
diff --git a/resources/static/dialog/resources/internal_api.js b/resources/static/dialog/resources/internal_api.js
new file mode 100644
index 0000000000000000000000000000000000000000..29bdd85d297ac251f83a7dd289b8b0ec85057f79
--- /dev/null
+++ b/resources/static/dialog/resources/internal_api.js
@@ -0,0 +1,140 @@
+/*jshint browsers:true, forin: true, laxbreak: true */
+/*global BrowserID: true*/
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla BrowserID.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+(function() {
+  "use strict";
+
+  var nav = navigator,
+      bid = BrowserID,
+      internal = bid.internal = bid.internal || {},
+      user = bid.User,
+      storage = bid.Storage,
+      moduleManager = bid.module;
+
+  /**
+   * Set the persistent flag to true for an origin.
+   * @method setPersistent
+   * @param {string} origin
+   * @param {string} email
+   * @param {callback} [callback] - callback to call when complete.  Called
+   * with true if successful, null if user is not authenticated or failure.
+   */
+  internal.setPersistent = function(origin, callback) {
+    function complete(status) {
+      callback && callback(status);
+    }
+
+    user.checkAuthentication(function onComplete(authenticated) {
+      if(authenticated) {
+        storage.site.set(origin, "remember", true);
+      }
+
+      complete(authenticated || null);
+    }, complete.bind(null, null));
+  };
+
+  /**
+   * Get an assertion.  Mimics the behavior of navigator.id.get.
+   * options.silent defaults to true.  To use the dialog to get an assertion,
+   * set options.silent to false. To specify a required email, set
+   * options.requiredEmail. By specifying both silent:true and requiredEmail:
+   * <email>, an assertion will be attempted to be retreived for the given
+   * email.
+   * @method get
+   * @param {string} origin
+   * @param {object} options.  See options block for navigator.id.get.
+   * options.silent defaults to true.
+   * @param {function} callback - called when complete.  Called with assertion
+   * if success, null if the user cancels.  Other conditions causing null
+   * return value: silent is true and user is not authenticated.  silent is
+   * true, requiredEmail is specified but user does not control email.
+   */
+  internal.get = function(origin, options, callback) {
+    function complete(assertion) {
+      // If no assertion, give no reason why there was a failure.
+      callback && callback(assertion || null);
+    }
+
+    var silent = options.silent !== false;
+    if(silent) {
+      // first, check the required email field, if that is not specified, go
+      // check if an email is associated with this site. If that is not
+      // available, there is not enough information to continue.
+      var requiredEmail = options.requiredEmail || storage.site.get(origin, "email");
+      if(requiredEmail) {
+        getSilent(origin, requiredEmail, callback);
+      }
+      else {
+        complete();
+      }
+    }
+    else {
+      // Use the standard dialog facilities to get the assertion, pass the
+      // options block directly to the dialog.
+      var controller = moduleManager.getModule("dialog");
+      if(controller) {
+        controller.get(origin, options, complete, complete);
+      }
+      else {
+        complete();
+      }
+    }
+  };
+
+  /*
+   * Get an assertion without user interaction - internal use
+   */
+  function getSilent(origin, email, callback) {
+    function complete(assertion) {
+      callback && callback(assertion);
+    }
+
+    user.checkAuthenticationAndSync(function onSuccess() {}, function onComplete(authenticated) {
+      // User must be authenticated to get an assertion.
+      if(authenticated) {
+        user.setOrigin(origin);
+        user.getAssertion(email, function(assertion) {
+          complete(assertion || null);
+        }, complete.bind(null, null));
+      }
+      else {
+        complete(null);
+      }
+    }, complete.bind(null, null));
+  }
+
+}());
diff --git a/resources/static/shared/user.js b/resources/static/shared/user.js
index fa362732edbda0cb5493509ae39dd5ecea55a78e..c093b48de9e41c4f2bc194a0af9b4d21806cdd01 100644
--- a/resources/static/shared/user.js
+++ b/resources/static/shared/user.js
@@ -642,7 +642,8 @@ BrowserID.User = (function() {
       // to avoid issues with clock drift on user's machine.
       // (issue #329)
         var storedID = storage.getEmail(email),
-            assertion;
+            assertion,
+            self=this;
 
         function createAssertion(idInfo) {
           network.serverTime(function(serverTime) {
@@ -658,6 +659,7 @@ BrowserID.User = (function() {
               // yield!
               setTimeout(function() {
                 assertion = vep.bundleCertsAndAssertion([idInfo.cert], tok.sign(sk));
+                storage.site.set(self.getOrigin(), "email", email);
                 if (onSuccess) {
                   onSuccess(assertion);
                 }
diff --git a/resources/static/test/qunit.html b/resources/static/test/qunit.html
index b05ae11393b474a044a436b03e3c83b798513a02..c145491f268649d29747f443ebe408542cce6a13 100644
--- a/resources/static/test/qunit.html
+++ b/resources/static/test/qunit.html
@@ -102,6 +102,7 @@
     <script type="text/javascript" src="/shared/validation.js"></script>
     <script type="text/javascript" src="/shared/helpers.js"></script>
 
+    <script type="text/javascript" src="/dialog/resources/internal_api.js"></script>
     <script type="text/javascript" src="/dialog/resources/channel.js"></script>
     <script type="text/javascript" src="/dialog/resources/helpers.js"></script>
     <script type="text/javascript" src="/dialog/resources/state_machine.js"></script>
@@ -148,6 +149,7 @@
     <script type="text/javascript" src="qunit/shared/network_unit_test.js"></script>
     <script type="text/javascript" src="qunit/shared/user_unit_test.js"></script>
 
+    <script type="text/javascript" src="qunit/resources/internal_api_unit_test.js"></script>
     <script type="text/javascript" src="qunit/resources/helpers_unit_test.js"></script>
     <script type="text/javascript" src="qunit/resources/state_machine_unit_test.js"></script>
     <script type="text/javascript" src="qunit/resources/channel_unit_test.js"></script>
diff --git a/resources/static/test/qunit/resources/channel_unit_test.js b/resources/static/test/qunit/resources/channel_unit_test.js
index 65bf19189c47f8b82de9457adebdc0f63734be83..878f2acbe0de4fe59db27a0b5052980c717e1536 100644
--- a/resources/static/test/qunit/resources/channel_unit_test.js
+++ b/resources/static/test/qunit/resources/channel_unit_test.js
@@ -132,6 +132,16 @@
     });
   });
 
+  test("IFRAME channel with #NATIVE channel specified", function() {
+    winMock.location.hash = "#NATIVE";
+
+    channel.open({
+      getVerifiedEmail: function(origin, onsuccess, onerror) {
+        ok(false, "getVerifiedEmail should not be called with a native channel");
+      }
+    });
+  });
+
   asyncTest("IFRAME channel with error on open", function() {
     delete winMock.opener.frames['1234'];
 
diff --git a/resources/static/test/qunit/resources/internal_api_unit_test.js b/resources/static/test/qunit/resources/internal_api_unit_test.js
new file mode 100644
index 0000000000000000000000000000000000000000..e4d01bedc41e9c9259b0f83c0b123fbb890aaf6c
--- /dev/null
+++ b/resources/static/test/qunit/resources/internal_api_unit_test.js
@@ -0,0 +1,220 @@
+/*jshint browsers:true, forin: true, laxbreak: true */
+/*global test: true, start: true, module: true, ok: true, equal: true, BrowserID:true */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla BrowserID.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+(function() {
+  "use strict";
+
+  var bid = BrowserID,
+      internal = bid.internal,
+      network = bid.Network,
+      user = bid.User,
+      xhr = bid.Mocks.xhr,
+      origin = "https://browserid.org",
+      storage = bid.Storage,
+      moduleManager = bid.module;
+
+  module("resources/internal_api", {
+    setup: function() {
+      network.setXHR(xhr);
+      xhr.useResult("valid");
+      xhr.setContextInfo("authenticated", false);
+      storage.clear();
+    },
+
+    teardown: function() {
+      network.setXHR($);
+    }
+  });
+
+  test("make sure internal api namespace is there", function() {
+    ok(bid.internal, "BrowserID.internal exists");
+  });
+
+  asyncTest("BrowserID.internal.setPersistent with the user not authenticated", function() {
+    internal.setPersistent(origin, function(status) {
+      strictEqual(status, null, "user is not authenticated should not succeed in setting persistent");
+
+      strictEqual(typeof storage.site.get(origin, "remember"), "undefined", "remember status not set");
+      strictEqual(typeof storage.site.get(origin, "email"), "undefined", "email not set");
+      start();
+    });
+  });
+
+  asyncTest("BrowserID.internal.setPersistent with authenticated user", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      internal.setPersistent(origin, function(status) {
+        equal(status, true, "setPersistent status reported as true");
+
+        equal(storage.site.get(origin, "remember"), true, "remember status set to true");
+        start();
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, non-authenticated user - returns null assertion", function() {
+    internal.get(origin, {
+        requiredEmail: "testuser@testuser.com"
+    }, function(assertion) {
+      strictEqual(assertion, null, "user not logged in, assertion impossible to get");
+      start();
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, no requiredEmail, and no email address associated with site - not enough info to generate an assertion", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      internal.get(origin, {}, function(assertion) {
+        strictEqual(assertion, null, "not enough info to generate an assertion, assertion should not be generated");
+        start();
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, no requiredEmail, email address associated with site, XHR failure - return null assertion.", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      user.syncEmails(function() {
+        storage.site.set(origin, "email", "testuser@testuser.com");
+
+        xhr.useResult("invalid");
+
+        internal.get(origin, {}, function(assertion) {
+          strictEqual(assertion, null, "XHR failure while getting assertion");
+          start();
+        });
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, no requiredEmail, email address associated with site - use info stored for site to get assertion", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      user.syncEmails(function() {
+        storage.site.set(origin, "email", "testuser@testuser.com");
+
+        internal.get(origin, {}, function(assertion) {
+          ok(assertion, "assertion generated using stored email address for site.");
+          start();
+        });
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, requiredEmail set to uncontrolled email address - return null assertion", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      // email addresses will not be synced just because we authenticated.
+      // Depending on get to do the sync.
+      internal.get(origin, {
+        requiredEmail: "invalid@testuser.com"
+      }, function(assertion) {
+        strictEqual(assertion, null, "uncontrolled email address returns null assertion");
+        start();
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, requiredEmail and XHR error - return null assertion", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      xhr.useResult("invalid");
+      internal.get(origin, {
+        requiredEmail: "invalid@testuser.com"
+      }, function(assertion) {
+        strictEqual(assertion, null, "unregistered email address returns null assertion");
+        start();
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with silent: true, authenticated user, requiredEmail, and registered email address - return an assertion", function() {
+    user.authenticate("testuser@testuser.com", "password", function() {
+      internal.get(origin, {
+        requiredEmail: "testuser@testuser.com"
+      }, function(assertion) {
+        ok(assertion, "assertion has been returned");
+        start();
+      });
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with dialog - return an assertion", function() {
+    moduleManager.reset();
+
+    moduleManager.register("dialog", {
+      get: function(getOrigin, options, onsuccess, onerror) {
+        equal(getOrigin, origin, "correct origin passed");
+        onsuccess("assertion");
+      }
+    });
+
+    internal.get(origin, {
+      silent: false
+    }, function onComplete(assertion) {
+        equal(assertion, "assertion", "Kosher assertion");
+        start();
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with dialog with failure - return null assertion", function() {
+    moduleManager.reset();
+
+    moduleManager.register("dialog", {
+      get: function(getOrigin, options, onsuccess, onerror) {
+        onerror();
+      }
+    });
+
+    internal.get(origin, {
+      silent: false
+    }, function onComplete(assertion) {
+        equal(assertion, null, "on failure, assertion is null");
+        start();
+    });
+  });
+
+  asyncTest("BrowserID.internal.get with dialog with user cancellation - return null assertion", function() {
+    moduleManager.reset();
+
+    moduleManager.register("dialog", {
+      get: function(getOrigin, options, onsuccess, onerror) {
+        onsuccess(null);
+      }
+    });
+
+    internal.get(origin, {
+      silent: false
+    }, function onComplete(assertion) {
+        equal(assertion, null, "on cancel, assertion is null");
+        start();
+    });
+  });
+}());
diff --git a/resources/static/test/qunit/shared/user_unit_test.js b/resources/static/test/qunit/shared/user_unit_test.js
index b2790de56a0a5981215e84b463107f3707530a86..e7c7e5b63dfc7c696973a1fd843d9f7aa2c3bcf3 100644
--- a/resources/static/test/qunit/shared/user_unit_test.js
+++ b/resources/static/test/qunit/shared/user_unit_test.js
@@ -96,6 +96,7 @@ var jwcert = require("./jwcert");
       xhr.useResult("valid");
       lib.clearStoredEmailKeypairs();
       lib.setOrigin(testOrigin);
+      storage.site.remove(testOrigin, "email");
     },
     teardown: function() {
       network.setXHR($);
@@ -787,6 +788,7 @@ var jwcert = require("./jwcert");
     lib.syncEmailKeypair("testuser@testuser.com", function() {
       lib.getAssertion("testuser@testuser.com", function onSuccess(assertion) {
         testAssertion(assertion, start);
+        equal(storage.site.get(testOrigin, "email"), "testuser@testuser.com", "email address was persisted");
       }, failure("getAssertion failure"));
     }, failure("syncEmailKeypair failure"));
   });
@@ -798,6 +800,7 @@ var jwcert = require("./jwcert");
     storage.addEmail("testuser@testuser.com", {});
     lib.getAssertion("testuser@testuser.com", function onSuccess(assertion) {
       testAssertion(assertion, start);
+      equal(storage.site.get(testOrigin, "email"), "testuser@testuser.com", "email address was persisted");
     }, failure("getAssertion failure"));
   });
 
@@ -806,6 +809,7 @@ var jwcert = require("./jwcert");
     lib.syncEmailKeypair("testuser@testuser.com", function() {
       lib.getAssertion("testuser2@testuser.com", function onSuccess(assertion) {
         equal("undefined", typeof assertion, "email was unknown, we do not have an assertion");
+        equal(storage.site.get(testOrigin, "email"), undefined, "email address was not set");
         start();
       });
     }, failure("getAssertion failure"));
@@ -840,7 +844,7 @@ var jwcert = require("./jwcert");
       }, failure("syncEmails failure"));
     }, failure("authenticate failure"));
 
-    
+
   });
 
   asyncTest("logoutUser with XHR failure", function(onSuccess) {
@@ -860,7 +864,7 @@ var jwcert = require("./jwcert");
       }, failure("syncEmails failure"));
     }, failure("authenticate failure"));
 
-    
+
   });
 
   asyncTest("cancelUser", function(onSuccess) {
@@ -870,7 +874,7 @@ var jwcert = require("./jwcert");
       start();
     });
 
-    
+
   });
 
   asyncTest("cancelUser with XHR failure", function(onSuccess) {
@@ -883,7 +887,7 @@ var jwcert = require("./jwcert");
       start();
     });
 
-    
+
   });
 
   asyncTest("getPersistentSigninAssertion with invalid login", function() {
@@ -903,7 +907,7 @@ var jwcert = require("./jwcert");
       });
     });
 
-    
+
   });
 
   asyncTest("getPersistentSigninAssertion with valid login with remember set to true but no email", function() {
@@ -919,7 +923,7 @@ var jwcert = require("./jwcert");
       start();
     });
 
-    
+
   });
 
   asyncTest("getPersistentSigninAssertion with valid login with email and remember set to false", function() {
@@ -940,7 +944,7 @@ var jwcert = require("./jwcert");
       });
     });
 
-    
+
   });
 
   asyncTest("getPersistentSigninAssertion with valid login, email, and remember set to true", function() {
@@ -961,7 +965,7 @@ var jwcert = require("./jwcert");
       });
     });
 
-    
+
   });
 
   asyncTest("getPersistentSigninAssertion with XHR failure", function() {
@@ -984,7 +988,7 @@ var jwcert = require("./jwcert");
       });
     });
 
-    
+
   });
 
   asyncTest("clearPersistentSignin with invalid login", function() {
@@ -998,7 +1002,7 @@ var jwcert = require("./jwcert");
       start();
     });
 
-    
+
   });
 
   asyncTest("clearPersistentSignin with valid login with remember set to true", function() {
@@ -1014,6 +1018,6 @@ var jwcert = require("./jwcert");
       start();
     });
 
-    
+
   });
 }());
diff --git a/scripts/compress.sh b/scripts/compress.sh
index 68fbaa0d1e2c97f1d669ef3cf382606d7eb1a2c1..77842a832ba6a0e5ddfa3ce1b8328ebf22bb8bcb 100755
--- a/scripts/compress.sh
+++ b/scripts/compress.sh
@@ -42,7 +42,7 @@ cp shared/templates.js shared/templates.js.orig
 cp dialog/views/templates.js shared/templates.js
 
 # produce the dialog js
-cat dialog/resources/channel.js lib/jquery-1.6.2.min.js lib/jschannel.js lib/underscore-min.js lib/vepbundle.js lib/ejs.js shared/browserid.js lib/hub.js lib/dom-jquery.js lib/module.js shared/javascript-extensions.js shared/mediator.js shared/class.js shared/storage.js shared/templates.js shared/renderer.js shared/error-display.js shared/screens.js shared/tooltip.js shared/validation.js shared/network.js shared/user.js shared/error-messages.js shared/browser-support.js shared/wait-messages.js shared/helpers.js dialog/resources/helpers.js dialog/resources/state_machine.js dialog/controllers/page.js dialog/controllers/dialog.js dialog/controllers/authenticate.js dialog/controllers/forgotpassword.js dialog/controllers/checkregistration.js dialog/controllers/pickemail.js dialog/controllers/addemail.js dialog/controllers/required_email.js dialog/start.js > dialog/production.js
+cat dialog/resources/channel.js lib/jquery-1.6.2.min.js lib/jschannel.js lib/underscore-min.js lib/vepbundle.js lib/ejs.js shared/browserid.js lib/hub.js lib/dom-jquery.js lib/module.js shared/javascript-extensions.js shared/mediator.js shared/class.js shared/storage.js shared/templates.js shared/renderer.js shared/error-display.js shared/screens.js shared/tooltip.js shared/validation.js shared/network.js shared/user.js shared/error-messages.js shared/browser-support.js shared/wait-messages.js shared/helpers.js dialog/resources/internal_api.js dialog/resources/helpers.js dialog/resources/state_machine.js dialog/controllers/page.js dialog/controllers/dialog.js dialog/controllers/authenticate.js dialog/controllers/forgotpassword.js dialog/controllers/checkregistration.js dialog/controllers/pickemail.js dialog/controllers/addemail.js dialog/controllers/required_email.js dialog/start.js > dialog/production.js
 
 # produce the non interactive frame js
 cat lib/jquery-1.6.2.min.js lib/jschannel.js lib/underscore-min.js lib/vepbundle.js shared/javascript-extensions.js shared/browserid.js shared/storage.js shared/network.js shared/user.js communication_iframe/start.js > communication_iframe/production.js