diff --git a/ChangeLog b/ChangeLog
index a2e7f3ae24920567d2acba932cb5f5ffa8888c8a..87040e9dfcabf257e202b9adcdf208d4c74836dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,2 +1,12 @@
+train-2011.08.04:
+  * when user closes dialog without clicking "cancel", properly return 'null' to the webpage (via getVerifiedEmail callback) - issue #107
+  * improve checks to warn developer that prerequisite software is missing. issue #110
+  * parameterize software to support multiple deployment environments (dev/beta/prod) issues #102 & #52
+  * documentation updates.
+  * improved logging (using the winston logging framework for node.js)
+  * [website] fixed inclusion of youtube video (now over https to keep browsers from getting scared about mixed mode resource inclusion)
+
 train-1:
-  * beginning of time, everything is new.  
+  * beginning of time, everything is new.
+  * (2011.08.03) include youtube video embedding over https (issue #112)
+  * (2011.08.04) fix mozillalabs.com link in dialog (issue #116)
diff --git a/browserid/app.js b/browserid/app.js
index 2035aa9de4387f315a5bfda6dc52534e52ead8d7..f95f06a4b13ddf78bb23782fac6978b3b3f41fb2 100644
--- a/browserid/app.js
+++ b/browserid/app.js
@@ -18,6 +18,7 @@ secrets = require('./lib/secrets.js'),
 db = require('./lib/db.js'),
 configuration = require('../libs/configuration.js'),
 substitution = require('../libs/substitute.js');
+logging = require("../libs/logging.js");
 
 // open the databse
 db.open();
@@ -43,7 +44,8 @@ function router(app) {
 
   // this should probably be an internal redirect
   // as soon as relative paths are figured out.
-  app.get('/sign_in', function(req, res, next ){
+  app.get('/sign_in', function(req, res, next ) {
+    logging.userEntry('browserid', req);
     res.render('dialog.ejs', {
       title: 'A Better Way to Sign In',
       layout: false,
diff --git a/browserid/static/dialog/views/body.ejs b/browserid/static/dialog/views/body.ejs
index b2952fe21134287a155a77a177fe39fa730d00bb..c6bf237d66e99105e2c14f8e0295628dc6341725 100644
--- a/browserid/static/dialog/views/body.ejs
+++ b/browserid/static/dialog/views/body.ejs
@@ -13,6 +13,6 @@
 </div>
 
 <footer id="terms">
-    BrowserID is a <a target="_blank" href="http://mozillalabs.org">Mozilla Labs</a> service.
+    BrowserID is a <a target="_blank" href="http://mozillalabs.com">Mozilla Labs</a> service.
     See our <a target="_blank" href="https://browserid.org/tos">terms</a> and <a target="_blank" href="https://browserid.org/privacy">privacy policy</a>, or <a target="_blank" href="https://browserid.org/users">learn more</a>.
 </footer>
diff --git a/browserid/views/users.ejs b/browserid/views/users.ejs
index dc0a4f6d09346cdf1446f0873d91beefe986b9c7..97b25729dd23968bffd40153b97c3f1000f57e48 100644
--- a/browserid/views/users.ejs
+++ b/browserid/views/users.ejs
@@ -3,6 +3,6 @@
       As a user of BrowserID, you confirm your email addresses once. Then, you can sign into any web site that supports BrowserID with just two clicks.
       </p>
 
-      <center><iframe width="480" height="390" src="http://www.youtube.com/embed/l0t9yDLAmFo" frameborder="0" allowfullscreen></iframe></center>
+      <center><iframe width="480" height="390" src="https://www.youtube.com/embed/l0t9yDLAmFo" frameborder="0" allowfullscreen></iframe></center>
       
     </div>
diff --git a/libs/configuration.js b/libs/configuration.js
index b3cfa84f70ec3f3773e7f0e9503d555ae30db65d..2690dc1f2fa1eb02b72e072f1f0cca4e436cd439 100644
--- a/libs/configuration.js
+++ b/libs/configuration.js
@@ -25,25 +25,29 @@ const g_configs = {
     hostname: 'browserid.org',
     port: '443',
     scheme: 'https',
-    use_minified_resources: true
+    use_minified_resources: true,
+    log_path: '/home/browserid/var/'
   },
   development: {
     hostname: 'dev.diresworb.org',
     port: '443',
     scheme: 'https',
-    use_minified_resources: true
+    use_minified_resources: true,
+    log_path: '/home/browserid/var/'
   },
   beta: {
     hostname: 'diresworb.org',
     port: '443',
     scheme: 'https',
-    use_minified_resources: true
+    use_minified_resources: true,
+    log_path: '/home/browserid/var/'
   },
   local: {
     hostname: '127.0.0.1',
     port: '10002',
     scheme: 'http',
-    use_minified_resources: false
+    use_minified_resources: false,
+    log_path: './'
   }
 };
 
diff --git a/libs/logging.js b/libs/logging.js
new file mode 100644
index 0000000000000000000000000000000000000000..c34aaa0c15ad10cd60c1f1c93b3f7968fb02dc0e
--- /dev/null
+++ b/libs/logging.js
@@ -0,0 +1,52 @@
+const winston = require("winston");
+const configuration = require("./configuration");
+
+// go through the configuration and determine log location
+// for now we only log to one place
+// FIXME: separate logs depending on purpose?
+
+var log_path = configuration.get('log_path');
+var LOGGERS = [];
+
+function setupLogger(category) {
+  if (!log_path)
+    return console.log("no log path! Not logging!");
+
+  // don't create the logger if it already exists
+  if (LOGGERS[category])
+    return;
+
+  // FIXME: check if log_path is properly terminated
+  var filename = log_path + category + "-log.txt";
+
+  LOGGERS[category] = new (winston.Logger)({
+      transports: [new (winston.transports.File)({filename: filename})]
+    });
+}
+
+// entry is an object that will get JSON'ified
+exports.log = function(category, entry) {
+  // entry must have at least a type
+  if (!entry.type)
+    throw new Error("every log entry needs a type");
+
+  // setup the logger if need be
+  setupLogger(category);
+
+  // timestamp
+  entry.at = new Date().toUTCString();
+  
+  // if no logger, go to console (FIXME: do we really want to log to console?)
+  LOGGERS[category].info(JSON.stringify(entry));
+};
+
+// utility function to log a bunch of stuff at user entry point
+exports.userEntry = function(category, req) {
+  exports.log(category, {
+      type: 'signin',
+      browser: req.headers['user-agent'],
+      rp: req.headers['referer'],
+      // IP address (this probably needs to be replaced with the X-forwarded-for value
+      ip: req.connection.remoteAddress
+    });
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index 412487fdd73b89ea21dca8774b6f47cc80aea905..4884a848aa5bcf5020bfdef75dca8787d23d1f0d 100644
--- a/package.json
+++ b/package.json
@@ -16,5 +16,6 @@
     , "express-csrf": "0.3.2"
     , "uglify-js": "1.0.6"
     , "JSONSelect": "0.2.1"
+    , "winston" : "0.3.3"
   }
 }
diff --git a/scripts/branch_train.sh b/scripts/branch_train.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fe73cf673fa3ea34fc8764f80add229ef1528fcb
--- /dev/null
+++ b/scripts/branch_train.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+git branch train-$(date +'%Y.%m.%d') dev
+
diff --git a/verifier/app.js b/verifier/app.js
index 2503a31be9d9a96453519c08f6a5a04623e69773..740311628d5b61c10b057ce1f4843313cd60e87d 100644
--- a/verifier/app.js
+++ b/verifier/app.js
@@ -5,6 +5,7 @@ const   path = require('path'),
  idassertion = require('./lib/idassertion.js'),
          jwt = require('./lib/jwt.js'),
      express = require('express');
+     logging = require('../libs/logging.js');
 
 // create the var directory if it doesn't exist
 var VAR_DIR = path.join(__dirname, "var");
@@ -35,6 +36,13 @@ function doVerify(req, resp, next) {
       .verify(
         audience,
         function(payload) {
+          // log it!
+          logging.log('verifier', {
+              type: 'verify',
+                result: 'success',
+                rp: payload.audience
+            });
+          
           result = {
             status : "okay",
             email : payload.email,
@@ -45,11 +53,21 @@ function doVerify(req, resp, next) {
           resp.json(result);
         },
         function(errorObj) {
+          logging.log('verifier', {
+              type: 'verify',
+                result: 'failure',
+                rp: audience
+            });
           resp.json({ status: "failure", reason: errorObj });
         }
       );
   } catch (e) {
     console.log(e.stack);
+    logging.log('verifier', {
+        type: 'verify',
+          result: 'failure',
+          rp: audience
+          });
     resp.json({ status: "failure", reason: e.toString() });
   }
 }