Index: Dev/trunk/src/server/config/check-couchdb.js
===================================================================
--- Dev/trunk/src/server/config/check-couchdb.js	(revision 481)
+++ Dev/trunk/src/server/config/check-couchdb.js	(revision 487)
@@ -7,6 +7,6 @@
 var schema = require('./couchdb-schema');
 
-module.exports = function(couchDbURL) {
-    var server = new CouchDB(couchDbURL);
+module.exports = function(couchServerURL,dbName) {
+    var server = new CouchDB(couchServerURL,dbName);
     var designRe = /^_design\//;
     return server.get('/_all_docs')
Index: Dev/trunk/src/server/config/config-couchdb.js
===================================================================
--- Dev/trunk/src/server/config/config-couchdb.js	(revision 481)
+++ Dev/trunk/src/server/config/config-couchdb.js	(revision 487)
@@ -5,8 +5,8 @@
   ;
 
-var designDocs = require('./couchdb-design-docs');
+module.exports = function(couchServerURL, dbName, designDocs) {
+    var server = new CouchDB(couchServerURL);
 
-module.exports = function(couchServerURL) {
-    var server = new CouchDB(couchServerURL);
+    if ( !designDocs ) { throw new Error("Forgot to pass design docs to checkCouch."); }
 
     console.log("Configuring CouchDB for QED");
@@ -14,8 +14,8 @@
     return server.get('')
     .then(function(info){
-        if (info.version !== "1.2.0" ) {
+        if (info.version !== "1.4.0" ) {
             console.log("Found "+info.version+", only tested with CouchDB 1.2.0");
         } else {
-            console.log("CouchDB 1.2.0 found");
+            console.log("CouchDB 1.4.0 found");
         }
     }).then(function(res){
Index: Dev/trunk/src/server/config/couchdb-design-docs.js
===================================================================
--- Dev/trunk/src/server/config/couchdb-design-docs.js	(revision 481)
+++ Dev/trunk/src/server/config/couchdb-design-docs.js	(revision 487)
@@ -11,5 +11,5 @@
 
     "qed/schemaInfo": {
-        version: "1"
+        version: "2"
     },
 
@@ -31,5 +31,7 @@
         language: "javascript",
         validate_doc_update: function(newDoc, oldDoc, userCtx, secObj) {
-            if ( oldDoc && oldDoc.publicationDate ) { throw({forbidden:'Published documents cannot be modified.'}); }
+            if ( oldDoc && oldDoc.publicationDate ) {
+                throw({forbidden:'Published documents cannot be modified.'});
+            }
         },
         views: {
@@ -59,8 +61,8 @@
                     if ( doc.categories && doc.categories.length > 0 ) {
                         for ( var i = 0; i < doc.categories.length; i++ ) { 
-                            emit([doc.categories[i],doc.topic||null],1);
+                            emit([doc.categories[i],doc.topic||"(default)"],1);
                         } 
                     } else { 
-                        emit([null,null],1); 
+                        emit(["(default)","(default)"],1); 
                     } 
                 },
@@ -72,8 +74,8 @@
                     if ( doc.categories && doc.categories.length > 0 ) {
                         for ( var i = 0; i < doc.categories.length; i++ ) {
-                            emit([doc.categories[i],doc.topic||null],1);
+                            emit([doc.categories[i],doc.topic||"(default)"],1);
                         }
                     } else {
-                        emit([null,null],1);
+                        emit(["(default)","(default)"],1);
                     }
                 },
@@ -83,14 +85,20 @@
                 map: function(doc){
                     if( doc.type !== 'Question' ){ return; }
-                    emit(doc.topic);
+                    emit(doc.topic||"(default)",1);
                 },
-                reduce: function(key, values, rereduce) { return null; }
+                reduce: function(key, values, rereduce) { return sum(values); }
             },
             published_topics: {
                 map: function(doc){
                     if ( doc.type !== 'Question' || !doc.publicationDate ) { return; }
-                    emit(doc.topic);
+                    emit(doc.topic||"(default)",1);
                 },
-                reduce: function(key, values, rereduce) { return null; }
+                reduce: function(key, values, rereduce) { return sum(values); }
+            },
+            by_code: {
+                map: function(doc){
+                    if ( doc.type !== 'Question' ) { return; }
+                    emit(doc.code,doc);
+                }
             }
         }
Index: Dev/trunk/src/server/config/couchdb-schema.json
===================================================================
--- Dev/trunk/src/server/config/couchdb-schema.json	(revision 481)
+++ Dev/trunk/src/server/config/couchdb-schema.json	(revision 487)
@@ -1,129 +1,144 @@
 {
+  "$schema": "http://json-schema.org/draft-04/schema#",
   "title": "QED Object Schema",
-  "version": "1",
+  "version": "2",
   "type": "object",
   "oneOf": [
-    { "$ref": "#/schemaInfo" },
-    { "$ref": "#/docTypes/any" }
+    { "$ref": "#/definitions/schemaInfo" },
+    { "$ref": "#/definitions/docs/any" }
   ],
-  "schemaInfo": {
-    "type": "object",
-    "properties": {
-        "_id": { "type": "string", "pattern": "schemaInfo" },
-        "_rev": { "type": "string", "optional": true },
-        "version": { "type": "string" }
-    },
-    "additionalProperties": false
-  },
-  "docTypes": {
-    "any": {
+  "definitions": {
+    "schemaInfo": {
       "type": "object",
-      "oneOf": [
-        { "$ref": "#/docTypes/Question" },
-        { "$ref": "#/docTypes/Survey" },
-        { "$ref": "#/docTypes/SurveyRun" },
-        { "$ref": "#/docTypes/Response" }
-      ]
-    },
-    "Question": {
       "properties": {
-        "type": { "type": "string", "pattern": "Question" },
-        "_id": { "type": "string", "optional": true },
-        "_rev": { "type": "string", "optional": true },
-        "categories": { "type": "array", "items": { "type": "string" } },
-        "code": { "type": "string" },
-        "content": { "type": "array", "items": { "$ref": "#/contentTypes/any" } },
-        "description": { "type": "string", "optional": true },
-        "publicationDate": { "type": "string", "pattern": "", "optional": true },
-        "title": { "type": "string" },
-        "topic": { "type": "string", "optional": true }
+          "_id": { "type": "string", "pattern": "schemaInfo" },
+          "_rev": { "type": "string" },
+          "version": { "type": "string" }
       },
+      "required": ["_id","version"],
       "additionalProperties": false
     },
-    "Survey": {
-      "type": "object",
-      "properties": {
-        "type": { "type": "string", "pattern": "Survey" },
-        "_id": { "type": "string", "optional": true },
-        "_rev": { "type": "string", "optional": true },
-        "publicationDate": { "type": "string", "pattern": "", "optional": true },
-        "questions": { "type": "array", "items": { "$ref": "#/docTypes/Question" } },
-        "title": { "type": "string" }
+    "docs": {
+      "any": {
+        "type": "object",
+        "oneOf":[
+          { "$ref": "#/definitions/docs/Question" },
+          { "$ref": "#/definitions/docs/Survey" },
+          { "$ref": "#/definitions/docs/SurveyRun" },
+          { "$ref": "#/definitions/docs/Response" }
+        ]
       },
-      "additionalProperties": false
-    },
-    "SurveyRun": {
-      "type": "object",
-      "properties": {
-        "type": { "type": "string", "pattern": "SurveyRun" },
-        "_id": { "type": "string", "optional": true },
-        "_rev": { "type": "string", "optional": true },
-        "description": { "type": "string" },
-        "endDate": { "type": "string", "pattern": "" },
-        "mode": { "type": "string", "enum": [ "open", "closed" ] },
-        "startDate": { "type": "string", "pattern": "" },
-        "survey": { "$ref": "#/docTypes/Survey" },
-        "title": { "type": "string" }
-      },
-      "additionalProperties": false
-    },
-    "Response": {
-      "type": "object",
-      "properties": {
-        "type": { "type": "string", "pattern": "Response" },
-        "_id": { "type": "string", "optional": true },
-        "_rev": { "type": "string", "optional": true },
-        "answers": { "type": "object" },
-        "publicationDate": { "type": "string", "pattern": "", "optional": true },
-        "surveyRunId": { "type": "string" }
-      },
-      "additionalProperties": false
-    }
-  },
-  "contentTypes": {
-    "any": {
-      "type": "object",
-      "oneOf": [
-        { "$ref": "#/contentTypes/Text" },
-        { "$ref": "#/contentTypes/StringInput" },
-        { "$ref": "#/contentTypes/ScaleInput" }
-      ]
-    },
-    "Text": {
+      "Question": {
         "type": "object",
         "properties": {
-            "type": { "type": "string", "pattern": "Text" },
-            "text": { "type": "string" }
+          "type": { "type": "string", "pattern": "Question" },
+          "_id": { "type": "string" },
+          "_rev": { "type": "string" },
+          "categories": { "type": "array", "items": { "type": "string" } },
+          "code": { "type": "string" },
+          "content": { "type": "array", "items": { "$ref": "#/definitions/content/any" } },
+          "description": { "type": "string" },
+          "publicationDate": { "type": "string", "format": "datetime" },
+          "title": { "type": "string" },
+          "topic": { "type": "string" }
         },
+        "required": ["type","categories","code","content","title"],
         "additionalProperties": false
-    },
-    "StringInput": {
+      },
+      "Survey": {
         "type": "object",
         "properties": {
-            "type": { "type": "string", "pattern": "StringInput" },
-            "text": { "type": "string" }
+          "type": { "type": "string", "pattern": "Survey" },
+          "_id": { "type": "string" },
+          "_rev": { "type": "string" },
+          "publicationDate": { "type": "string", "format": "datetime" },
+          "questions": { "type": "array", "items": { "$ref": "#/definitions/docs/Question" } },
+          "title": { "type": "string" }
         },
+        "required": ["type","questions","title"],
         "additionalProperties": false
-    },
-    "ScaleInput": {
+      },
+      "SurveyRun": {
         "type": "object",
         "properties": {
-            "type": { "type": "string", "pattern": "ScaleInput" },
-            "minLabel": { "type": "string", "optional": true },
-            "min": { "type": "integer" },
-            "max": { "type": "integer" },
-            "maxLabel": { "type": "string", "optional": true },
-            "naLabel": { "type": "string", "optional": true },
-            "items": { "type": "array", "items": {
-                "type": "object",
-                "properties": {
-                    "text": { "type": "string" },
-                    "minLabel": { "type": "string", "optional": true },
-                    "maxLabel": { "type": "string", "optional": true }
-                },
-                "additionalProperties": false
-            } }
+          "type": { "type": "string", "pattern": "SurveyRun" },
+          "_id": { "type": "string" },
+          "_rev": { "type": "string" },
+          "description": { "type": "string" },
+          "endDate": { "type": "string", "format": "datetime" },
+          "mode": { "type": "string", "enum": [ "open", "closed" ] },
+          "secret": { "type": "string", "minLength": 8 },
+          "startDate": { "type": "string", "format": "datetime" },
+          "survey": { "$ref": "#/definitions/docs/Survey" },
+          "title": { "type": "string" }
         },
+        "required": ["type","description","mode","secret","survey","title"],
         "additionalProperties": false
+      },
+      "Response": {
+        "type": "object",
+        "properties": {
+          "type": { "type": "string", "pattern": "Response" },
+          "_id": { "type": "string" },
+          "_rev": { "type": "string" },
+          "answers": { "type": "object" },
+          "publicationDate": { "type": "string", "format": "datetime" },
+          "secret": { "type": "string", "minLength": 8 },
+          "surveyRunId": { "type": "string" }
+        },
+        "required": ["type","answers","secret","surveyRunId"],
+        "additionalProperties": false
+      }
+    },
+    "content":{
+      "any": {
+        "type": "object",
+        "oneOf": [
+          { "$ref": "#/definitions/content/Text" },
+          { "$ref": "#/definitions/content/StringInput" },
+          { "$ref": "#/definitions/content/ScaleInput" }
+        ]
+      },
+      "Text": {
+        "type": "object",
+        "properties": {
+          "type": { "type": "string", "pattern": "Text" },
+          "text": { "type": "string" }
+        },
+        "required": ["type","text"],
+        "additionalProperties": false
+      },
+      "StringInput": {
+        "type": "object",
+        "properties": {
+          "type": { "type": "string", "pattern": "StringInput" },
+          "text": { "type": "string" }
+        },
+        "required":["type","text"],
+        "additionalProperties": false
+      },
+      "ScaleInput": {
+        "type": "object",
+        "properties": {
+          "type": { "type": "string", "pattern": "ScaleInput" },
+          "minLabel": { "type": "string" },
+          "min": { "type": "integer" },
+          "max": { "type": "integer" },
+          "maxLabel": { "type": "string" },
+          "naLabel": { "type": "string" },
+          "items": { "type": "array", "items": {
+            "type": "object",
+            "properties": {
+              "text": { "type": "string" },
+              "minLabel": { "type": "string" },
+              "maxLabel": { "type": "string" }
+            },
+            "required":["text"],
+            "additionalProperties": false
+          } }
+        },
+        "required":["type","min","max","items"],
+        "additionalProperties": false
+      }
     }
   }
Index: Dev/trunk/src/server/config/couchdb-upgrade-design-docs.js
===================================================================
--- Dev/trunk/src/server/config/couchdb-upgrade-design-docs.js	(revision 487)
+++ Dev/trunk/src/server/config/couchdb-upgrade-design-docs.js	(revision 487)
@@ -0,0 +1,11 @@
+module.exports = {
+
+    "qed/schemaInfo": {
+        version: "-1"
+    },
+
+    "qed/_design/default": {
+        __configAction: "replace"
+    }
+
+};
Index: Dev/trunk/src/server/config/upgrade-couchdb.js
===================================================================
--- Dev/trunk/src/server/config/upgrade-couchdb.js	(revision 487)
+++ Dev/trunk/src/server/config/upgrade-couchdb.js	(revision 487)
@@ -0,0 +1,38 @@
+var Q = require('q')
+  , _ = require('underscore')
+  , tv4 = require('tv4')
+  , CouchDB = require('../util/couch').CouchDB
+  ;
+
+var schema = require('./couchdb-schema');
+
+module.exports = function(couchServerURL,dbName,upgrade) {
+    var server = new CouchDB(couchServerURL,dbName);
+    var designRe = /^_design\//;
+    return server.get('/_all_docs')
+    .then(function(allDocs){
+        return _.chain(allDocs.rows)
+        .filter(function(doc){
+            return doc.id.match(designRe) === null;
+        })
+        .reduce(function(memo, doc){
+            return memo.then(function(result){
+                return server.get(doc.id)
+                .then(function(doc){
+                    Q.when(upgrade(doc))
+                    .then(function(newDoc){
+                        return server.put(doc._id,newDoc)
+                        .then(function(){
+                            result[doc._id] = true;
+                            return result;
+                        });
+                    },function(){
+                        result[doc._id] = false;
+                    });
+                    return result;
+                });
+            });
+        }, Q.resolve({}))
+        .value();
+    }).all();
+};
