Index: Dev/trunk/src/client/qed-client/app/Router.js
===================================================================
--- Dev/trunk/src/client/qed-client/app/Router.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/app/Router.js	(revision 487)
@@ -78,5 +78,5 @@
                         route.callback(params);
                     } catch(err) {
-                        console.error("Page change failed with",err.toString());
+                        console.error("Page change failed with",err,err.toString());
                     }
                     return;
Index: Dev/trunk/src/client/qed-client/model/classes/Question.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/Question.js	(revision 485)
+++ 	(revision )
@@ -1,20 +1,0 @@
-define(function(){
-    return {
-        create: function(){
-            return { type:'Question' };
-        },
-        DisplayTitle: {
-            get: function(q) {
-                return q.title || '';
-            }
-        },
-        Content: {
-            get: function(q) {
-                return q.content || [];
-            },
-            set: function(q,content) {
-                q.content = content;
-            }
-        }
-    };
-});
Index: Dev/trunk/src/client/qed-client/model/classes/Response.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/Response.js	(revision 485)
+++ 	(revision )
@@ -1,17 +1,0 @@
-define([],function(){
-    var SurveyRun = {
-        create: function(){
-            return { type:'Response' };
-        },
-        SurveyRun: {
-            get: function(r) {
-                return r.surveyRunId || null;
-            },
-            set: function(r,sr) {
-                r.surveyRunId = sr;
-                return r;
-            }
-        }
-    };
-    return SurveyRun;
-});
Index: Dev/trunk/src/client/qed-client/model/classes/SessionTemplate.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/SessionTemplate.js	(revision 485)
+++ 	(revision )
@@ -1,12 +1,0 @@
-define(function(){
-    return {
-        create: function(){
-            return { type:'SessionTemplate' };
-        },
-        DisplayTitle: {
-            get: function(st) {
-                return st.title || '';
-            }
-        }
-    };
-});
Index: Dev/trunk/src/client/qed-client/model/classes/Survey.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/Survey.js	(revision 485)
+++ 	(revision )
@@ -1,20 +1,0 @@
-define(function(){
-    return {
-        create: function(){
-            return { type:'Survey' };
-        },
-        DisplayTitle: {
-            get: function(s) {
-                return s.title || '';
-            }
-        },
-        Questions: {
-            get: function(s) {
-                return s.questions || [];
-            },
-            set: function(s,questions) {
-                s.questions = questions;
-            }
-        }
-    };
-});
Index: Dev/trunk/src/client/qed-client/model/classes/SurveyRun.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/SurveyRun.js	(revision 485)
+++ 	(revision )
@@ -1,57 +1,0 @@
-define(['dojo/_base/lang','dojo/date/locale','dojo/date/stamp'],function(lang,locale,stamp){
-    var SurveyRun = {
-        create: function(){
-            return { type:'SurveyRun' };
-        },
-        StartDate: {
-            get: function(sr) {
-                var d;
-                if ( sr.startDate ) {
-                    d = lang.isString(sr.startDate) ? stamp.fromISOString(sr.startDate) : sr.startDate;
-                }
-                return d;
-            },
-            set: function(sr,d) {
-                if ( d ) {
-                    sr.startDate = lang.isString(d) ? stamp.toISOString(d) : d;
-                }
-            }
-        },
-        EndDate: {
-            get: function(sr) {
-                var d;
-                if ( sr.endDate ) {
-                    d = lang.isString(sr.endDate) ? stamp.fromISOString(sr.endDate) : sr.endDate;
-                }
-                return d;
-            },
-            set: function(sr,d) {
-                if ( d ) {
-                    sr.endDate = lang.isString(d) ? stamp.toISOString(d) : d;
-                }
-            }
-        },
-        DisplayTitle: {
-            get: function(sr) {
-                var t = "Run of '"+sr.survey.title+"'";
-                if ( sr.startDate ) {
-                    t += " from "+locale.format(SurveyRun.StartDate.get(sr));
-                }
-                if ( sr.endDate ) {
-                    t += " until "+locale.format(SurveyRun.EndDate.get(sr));
-                }
-                return t;
-            }
-        },
-        Survey: {
-            get: function(sr) {
-                return sr.survey || null;
-            },
-            set: function(sr,s) {
-                sr.survey = s;
-                return sr;
-            }
-        }
-    };
-    return SurveyRun;
-});
Index: Dev/trunk/src/client/qed-client/model/classes/_Class.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/_Class.js	(revision 487)
@@ -0,0 +1,51 @@
+define([
+    "./_View",
+    "dojo/_base/declare",
+    "dojo/_base/lang"
+], function(_View, declare, lang) {
+
+    var _Class = declare([_View],{
+        _type: null,
+        constructor: function() {
+            if ( this._type === null ) {
+                throw new Error("You must specify a concrete type.");
+            }
+        },
+        create: function() {
+            var obj = {
+                type: this._type
+            };
+            console.warn("You may want to override create for concrete types.");
+            return obj;
+        },
+        _doSerialize: function(obj) {
+            obj = lang.clone(obj);
+            return this._serialize(obj) || obj;
+        },
+        _serialize: function(obj) {
+            console.warn("You may want to override _serialize for concrete types.");
+        },
+        load: function(id) {
+            return this._store.get(id).then(lang.hitch(this,'_doDeserialize'));
+        },
+        save: function(obj) {
+            return this._store.put(this._doSerialize(obj));
+        },
+        remove: function(objOrId,rev) {
+            var id;
+            if ( typeof objOrId === "string" ) {
+                id = objOrId;
+            } else {
+                id = this.getId(objOrId);
+                rev = this.getRev(objOrId);
+            }
+            return this._store.remove(id,{headers:{'If-Match':'"'+rev+'"'}});
+        },
+        getRev: function(obj) {
+            return obj._rev;
+        }
+    });
+
+    return _Class;
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/_View.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/_View.js	(revision 487)
@@ -0,0 +1,37 @@
+define([
+    "../../store/JsonRest",
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/store/util/QueryResults"
+], function(JsonRest, declare, lang, queryResults) {
+
+    var _View = declare([],{
+        _collection: null,
+        _store: null,
+        constructor: function() {
+            if ( this._collection === null ) {
+                throw new Error("You must specify a concrete collection.");
+            }
+            this._store = new JsonRest({
+                target: '/api/'+this._collection+'/',
+                idProperty: '_id'
+            });
+        },
+        _doDeserialize: function(obj) {
+            obj = lang.clone(obj);
+            return this._deserialize(obj) || obj;
+        },
+        _deserialize: function(obj) {
+            console.warn("You may want to override _deserialize for concrete types.");
+        },
+        query: function(query) {
+            return queryResults(this._store.query(query).map(lang.hitch(this,'_doDeserialize')));
+        },
+        getId: function(obj) {
+            return obj._id;
+        }
+    });
+
+    return _View;
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/categories.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/categories.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/categories.js	(revision 487)
@@ -0,0 +1,16 @@
+define([
+    "./_View",
+    "dojo/_base/declare"
+], function(_View, declare) {
+
+    var Categories = declare([_View],{
+        _collection: 'categories',
+        _deserialize: function() {},
+        getId: function(obj) {
+            return obj;
+        }
+    });
+
+    return new Categories();
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/questions.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/questions.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/questions.js	(revision 487)
@@ -0,0 +1,34 @@
+define([
+    "./_Class",
+    "dojo/_base/declare",
+    "dojo/date/stamp"
+], function(_Class, declare, stamp) {
+
+    var Questions = declare([_Class],{
+        _collection: 'questions',
+        _type: 'Question',
+        create: function() {
+            var obj = {
+                type: this._type,
+                categories: [],
+                code: "",
+                content: [],
+                title: ""
+            };
+            return obj;
+        },
+        _deserialize: function(obj) {
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+            }
+        },
+        _serialize: function(obj) {
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+            }
+        }
+    });
+
+    return new Questions();
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/responses.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/responses.js	(revision 487)
@@ -0,0 +1,93 @@
+define([
+    "./_Class",
+    "./surveyRuns",
+    "dojo/Deferred",
+    "dojo/_base/declare",
+    "dojo/_base/json",
+    "dojo/_base/lang",
+    "dojo/_base/xhr",
+    "dojo/date/stamp"
+], function(_Class, surveyRuns, Deferred, declare, json, lang, xhr, stamp) {
+
+    var Responses = declare([_Class],{
+        _collection: 'responses',
+        _type: 'Response',
+        create: function() {
+            var obj = {
+                type: this._type,
+                answers: {},
+                surveyRunId: null
+            };
+            return obj;
+        },
+        _deserialize: function(obj) {
+            if (obj._surveyRun) {
+                obj._surveyRun = surveyRuns._doDeserialize(obj._surveyRun);
+            }
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+            }
+        },
+        _serialize: function(obj) {
+            if (obj._surveyRun) {
+                obj._surveyRun = surveyRuns._doSerialize(obj._surveyRun);
+            }
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+            }
+        },
+        getWithSecret: function(id,secret) {
+            var query = xhr.objectToQuery({secret:secret});
+            return xhr('GET',{
+                url: '/api/open/responses/' + id + '?' + query,
+                handleAs: 'json',
+                contentType: false
+            }).then(lang.hitch(this,'_doDeserialize'),function(err){
+                return new Deferred().reject(json.fromJson(err.responseText));
+            });
+        },
+        postWithSecret: function(response,secret) {
+            var query = xhr.objectToQuery({secret:secret});
+            var body = json.toJson(this._doSerialize(response));
+            return xhr('POST',{
+                url: '/api/open/responses?' + query,
+                handleAs: 'json',
+                contentType: 'application/json',
+                rawBody: body
+            }).then(lang.hitch(this,'_doDeserialize'),function(err){
+                return new Deferred().reject(json.fromJson(err.responseText));
+            });
+        },
+        putWithSecret: function(response,secret) {
+            var query = xhr.objectToQuery({secret:secret});
+            var body = json.toJson(this._doSerialize(response));
+            return xhr('PUT',{
+                url: '/api/open/responses/' + this.getId(response) + '?' + query,
+                handleAs: 'json',
+                contentType: 'application/json',
+                rawBody: body
+            }).then(lang.hitch(this,'_doDeserialize'),function(err){
+                return new Deferred().reject(json.fromJson(err.responseText));
+            });
+        },
+        removeWithSecret: function(response,secret) {
+            var query = xhr.objectToQuery({secret:secret});
+            var rev = this.getRev(response);
+            var body = json.toJson(this._doSerialize(response));
+            var headers = {};
+            if ( rev ) {
+                headers['If-Match'] = '"'+rev+'"';
+            }
+            return xhr('DELETE',{
+                url: '/api/open/responses/' + this.getId(response) + '?' + query,
+                headers: headers,
+                handleAs: 'json',
+                contentType: 'application/json',
+                rawBody: body
+            });
+        }
+    });
+
+    return new Responses();
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js	(revision 487)
@@ -0,0 +1,47 @@
+define([
+    "./_Class",
+    "./surveys",
+    "dojo/_base/declare",
+    "dojo/date/stamp"
+], function(_Class, surveys, declare, stamp) {
+
+    var SurveyRuns = declare([_Class],{
+        _collection: 'surveyRuns',
+        _type: 'SurveyRun',
+        create: function() {
+            var obj = {
+                type: this._type,
+                description: "",
+                mode: "open",
+                survey: null,
+                title: ""
+            };
+            return obj;
+        },
+        _deserialize: function(obj) {
+            if (obj.endDate) {
+                obj.endDate = stamp.fromISOString(obj.endDate);
+            }
+            if (obj.startDate) {
+                obj.startDate = stamp.fromISOString(obj.startDate);
+            }
+            if (obj.survey) {
+                obj.survey = surveys._doDeserialize(obj.survey);
+            }
+        },
+        _serialize: function(obj) {
+            if (obj.endDate) {
+                obj.endDate = stamp.toISOString(obj.endDate);
+            }
+            if (obj.startDate) {
+                obj.startDate = stamp.toISOString(obj.startDate);
+            }
+            if (obj.survey) {
+                obj.survey = surveys._doSerialize(obj.survey);
+            }
+        }
+    });
+
+    return new SurveyRuns();
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/surveys.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/surveys.js	(revision 487)
@@ -0,0 +1,33 @@
+define([
+    "./_Class",
+    "dojo/_base/declare",
+    "dojo/date/stamp",
+    "dojo/store/JsonRest"
+], function(_Class, declare, stamp, JsonRest) {
+
+    var Surveys = declare([_Class],{
+        _collection: 'surveys',
+        _type: 'Survey',
+        create: function() {
+            var obj = {
+                type: this._type,
+                questions: [],
+                title: ""
+            };
+            return obj;
+        },
+        _deserialize: function(obj) {
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.fromISOString(obj.publicationDate);
+            }
+        },
+        _serialize: function(obj) {
+            if (obj.publicationDate) {
+                obj.publicationDate = stamp.toISOString(obj.publicationDate);
+            }
+        }
+    });
+
+    return new Surveys();
+
+});
Index: Dev/trunk/src/client/qed-client/model/classes/topics.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/classes/topics.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/model/classes/topics.js	(revision 487)
@@ -0,0 +1,16 @@
+define([
+    "./_View",
+    "dojo/_base/declare"
+], function(_View, declare) {
+
+    var Topics = declare([_View],{
+        _collection: 'topics',
+        _deserialize: function() {},
+        getId: function(obj) {
+            return obj;
+        }
+    });
+
+    return new Topics();
+
+});
Index: Dev/trunk/src/client/qed-client/model/schema.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/schema.js	(revision 485)
+++ 	(revision )
@@ -1,157 +1,0 @@
-define(['dojo/_base/lang'],function(lang){
-
-    /** Note on dojox.json.schema
-     * This implementation is not according to the version 03 of the json-schema
-     * draft. Differences:
-     * - doesn't support the 'required' property, but uses 'optional' (which is
-     *   false by default).
-     */
-
-    ////////////////////////////////////////
-    // Base schema types
-    //
-
-    var dateRe = "\\d{4}-\\d{2}-\\d{2}"; // YYYY-MM-DD
-    var timeRe = "\\d{2}:\\d{2}:\\d{2}"; // hh:mm:ss 
-    var datetimeRe = dateRe+"T"+timeRe+"Z"; // YYYY-MM-DDThh:mm:ssZ
-
-    function mixin(obj1,obj2) {
-        return lang.mixin({},obj1||{},obj2||{});
-    }
-    function mkType(base) {
-        return function(props) {
-            return mixin(base,props);
-        };
-    }
-
-    var nestring = mkType({ type:'string', minLength:1 });
-    var string = mkType({ type:'string' });
-    var integer = mkType({ type: 'integer' });
-    var bool = mkType({ type: 'boolean' });
-    var pattern = function(p){
-        return mixin({
-            type: 'string',
-            pattern: p
-        });
-    };
-    var date = mkType(pattern(dateRe));
-    var time = mkType(pattern(timeRe));
-    var datetime = mkType(pattern(datetimeRe));
-    var array = function(items,props) {
-        return mixin({
-            type: 'array',
-            items: items
-        },props);
-    };
-    var object = function(properties,props) {
-        return mixin({
-            type: 'object',
-            properties: properties,
-            additionalProperties: false
-        },props);
-    };
-    var optional = mkType({ optional: true });
-
-    ////////////////////////////////////////
-    // Domain specific
-    //
-
-    var typedobject = function(type,properties,props) {
-        return object(mixin(properties,{
-            type: pattern(type)
-        }),props);
-    };
-
-    var dbobject = function(type,properties,props) {
-        return typedobject(type,mixin(properties,{
-            _id: nestring(optional()),
-            _rev: nestring(optional())
-        }),props);
-    };
-
-    ////////////////////////////////////////
-    // The QED schema
-    //
-
-    var Respondent = dbobject('Respondent',{
-        secret: nestring()
-    });
-
-    var Question = dbobject('Question',{
-        code:nestring(),
-        title: nestring(),
-        description: string(optional()),
-        topic: string(optional()),
-        categories: array(nestring(),optional()),
-        content: array([
-            typedobject('Header',{
-                content:string(optional())
-            }),
-            typedobject('Text',{
-                content:string(optional())
-            }),
-            typedobject('Divider'),
-            typedobject('StringInput'),
-            typedobject('TextInput',{
-                maxLength:integer()
-            }),
-            typedobject('IntegerInput',{
-                min:integer(),
-                max:integer(),
-                step:integer()
-            }),
-            typedobject('MultipleChoiceInput',{
-                multiple:bool(),
-                items:array(nestring())
-            })
-        ],optional()),
-        publicationDate:datetime(optional())
-    });
-
-    var Survey = dbobject('Survey',{
-        title: nestring(),
-        description: string(optional()),
-        questions: array(Question,optional()),
-        publicationDate:datetime(optional())
-    });
-
-    var SurveyRun = dbobject('SurveyRun',{
-        description: string(optional()),
-        survey: Survey,
-        publicationDate:datetime(optional()),
-        startDate:datetime(optional()),
-        endDate:datetime(optional()),
-        mode:{type:'string','enum':['open','closed'],optional:true},
-        metadata:string(optional())
-    });
-
-    var Response = dbobject('Response',{
-        surveyRunId: nestring(),
-        answers:{type:'object',optional:true},
-        publicationDate:datetime(optional())
-    });
-
-    var Session = dbobject('Session',{
-        title: nestring(),
-        description: string(optional()),
-        publicationDate: datetime(optional())
-    });
-
-    var SessionTemplate = dbobject('SessionTemplate',{
-        title: nestring(),
-        description: string(optional()),
-        publicationDate: datetime(optional()),
-        plannedDate: datetime(optional())
-    });
-
-    var schema = {type:[
-        Question,
-        Survey,
-        SurveyRun,
-        Response,
-        Session,
-        SessionTemplate
-    ]};
-
-    return schema;
-});
Index: Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorToolkit.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorToolkit.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/model/widgets/QuestionEditorToolkit.js	(revision 487)
@@ -1,4 +1,5 @@
 define([
-    "../../store",
+    "../classes/categories",
+    "../classes/topics",
     "./CategoryListView",
     "dijit/_Container",
@@ -15,5 +16,5 @@
     "require",
     "dojo/text!./templates/QuestionEditorToolkit.html"
-], function(store, CategoryListView, _Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, Button, ComboBox, declare, lang, Source, domConstruct, Memory, require, template) {
+], function(categories, topics, CategoryListView, _Container, _TemplatedMixin, _WidgetBase, _WidgetsInTemplateMixin, Button, ComboBox, declare, lang, Source, domConstruct, Memory, require, template) {
     return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container], {
 
@@ -107,12 +108,10 @@
             this.inherited(arguments);
 
-            store.query("_design/questions/_view/all", {reduce:true, group:false, group_level:1})
-            .forPairs(lang.hitch(this, function(value, key) {
-                this._categoryStore.put({ id: key[0] });
+            categories.query().forEach(lang.hitch(this,function(cat){
+                this._categoryStore.put({ id: cat });
             }));
 
-            store.query("_design/questions/_view/all_topics", {reduce:true, group:true})
-            .forPairs(lang.hitch(this, function(value, key) {
-                this._topicStore.put({ id: key });
+            topics.query().forEach(lang.hitch(this,function(topic){
+                this._categoryStore.put({ id: topic });
             }));
         },
Index: Dev/trunk/src/client/qed-client/model/widgets/SurveyRenderWidget.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/SurveyRenderWidget.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/model/widgets/SurveyRenderWidget.js	(revision 487)
@@ -1,5 +1,4 @@
 define([
     "../../widgets/_ComplexValueWidget",
-    "../classes/Survey",
     "./questions/Factory",
     "dojo/_base/array",
@@ -7,5 +6,5 @@
     "dojo/dom-construct",
     "dojo/text!./templates/SurveyRenderWidget.html"
-], function(_ComplexValueWidget, Survey, QuestionWidgetFactory, array, declare, domConstruct, template) {
+], function(_ComplexValueWidget, QuestionWidgetFactory, array, declare, domConstruct, template) {
     return declare([_ComplexValueWidget],{
         templateString: template,
@@ -22,5 +21,5 @@
             this.survey = survey;
             var f = new QuestionWidgetFactory();
-            array.forEach(Survey.Questions.get(this.survey),function(question,question_index){
+            array.forEach(this.survey.questions,function(question,question_index){
                 array.forEach(question.content || [], function(item,item_index){
                     // The dot causes values to be grouped in an object!
Index: Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/model/widgets/SurveySummary.js	(revision 487)
@@ -1,5 +1,3 @@
 define([
-    "../../store",
-    "../classes/Survey",
     "dijit/_TemplatedMixin",
     "dijit/_WidgetBase",
@@ -7,5 +5,5 @@
     "dojo/dom-attr",
     "dojo/text!./templates/SurveySummary.html"
-], function(store, Survey, _TemplatedMixin, _WidgetBase, declare, domAttr, template) {
+], function(_TemplatedMixin, _WidgetBase, declare, domAttr, template) {
     return declare([_WidgetBase,_TemplatedMixin],{
         templateString: template,
@@ -18,9 +16,8 @@
         },
         _setValueAttr: function(survey) {
-            this.titleNode.innerHTML = Survey.DisplayTitle.get(survey);
-            var id = store.getIdentity(survey);
-            domAttr.set(this.titleNode, "href", id && ("#!/survey/"+id));
+            this.titleNode.innerHTML = survey.title || "";
+            domAttr.set(this.titleNode, "href", survey._id && ("#!/survey/"+survey._id));
             this.descriptionNode.innerHTML = survey.description;
-            this.questionsNode.innerHTML = (survey.questions || []).length;
+            this.questionsNode.innerHTML = survey.questions.length;
         }
     });
Index: Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js
===================================================================
--- Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js	(revision 487)
@@ -1,12 +1,14 @@
 define([
-    'dojo/_base/declare',
-    'dojo/_base/lang',
-    'dojo/_base/window',
-    'dijit/layout/ContentPane',
-    'dijit/layout/TabContainer',
-    'dojox/widget/Standby',
-    '../../store',
-    '../../widgets/Selector'
-],function(declare,lang,win,ContentPane,TabContainer,Standby,store,Selector){
+    "../../widgets/Selector",
+    "../classes/categories",
+    "../classes/questions",
+    "../classes/topics",
+    "dijit/layout/ContentPane",
+    "dijit/layout/TabContainer",
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/_base/window",
+    "dojox/widget/Standby"
+], function(Selector, categories, questions, topics, ContentPane, TabContainer, declare, lang, win, Standby) {
     return declare([TabContainer],{
         tabPosition: 'left-h',
@@ -38,7 +40,7 @@
                 this._fillCategoryTab(newTab.__category);
             }));
-            store.query(this._query, {reduce:true,group:true,group_level:1})
-            .forPairs(lang.hitch(this,function(value,key){
-                this._createCategoryTab(key[0],value);
+            categories.query()
+            .forEach(lang.hitch(this,function(cat){
+                this._createCategoryTab(cat.name,cat.count);
             }));
         },
@@ -61,7 +63,7 @@
                 this._busy();
                 categoryMap._filled = true;
-                store.query(this._query, {reduce:true,group:true,group_level:2,startkey:[category],endkey:[category,{}]})
-                .forPairs(lang.hitch(this,function(value,key){
-                    this._createTopicSelector(key[1],category,value);
+                topics.query({category:category})
+                .forEach(lang.hitch(this,function(topic){
+                    this._createTopicSelector(topic.name,category,topic.count);
                 })).then(lang.hitch(this,function(){
                     this._done();
@@ -101,9 +103,6 @@
                 topicMap._filled = true;
                 this._busy();
-                store.query(this._query, {
-                    reduce:false,
-                    include_docs:true,
-                    key:[category,topic]
-                }).forEach(lang.hitch(this,function(value){
+                questions.query({category:category,topic:topic})
+                .forEach(lang.hitch(this,function(value){
                     topicMap._widget.addItem(value);
                 })).then(lang.hitch(this,function(){
Index: Dev/trunk/src/client/qed-client/pages/previewSurvey.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/previewSurvey.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/previewSurvey.js	(revision 487)
@@ -1,5 +1,5 @@
 define([
     "../app/Page",
-    "../store",
+    "../model/classes/surveys",
     "dojo/_base/array",
     "dojo/_base/declare",
@@ -8,5 +8,5 @@
     "require",
     "dojo/text!./templates/previewSurvey.html"
-], function(Page, store, array, declare, lang, when, require, template) {
+], function(Page, surveys, array, declare, lang, when, require, template) {
     return declare([Page],{
         contextRequire: require,
@@ -16,7 +16,7 @@
             this.inherited(arguments);
             if ( this.surveyId ) {
-                when(store.get(this.surveyId))
+                when(surveys.load(this.surveyId))
                 .then(lang.hitch(this,function(survey){
-                    this.titleNode.innerHTML = survey.title;
+                    this.titleNode.innerHTML = survey.title || "";
                     this.surveyWidget.set('survey',survey);
                 }));
Index: Dev/trunk/src/client/qed-client/pages/question.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/question.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/question.js	(revision 487)
@@ -3,8 +3,7 @@
     "../app/Page",
     "../app/Router",
-    "../model/classes/Question",
+    "../model/classes/questions",
     "../model/widgets/QuestionEditorPreview",
     "../model/widgets/QuestionEditorToolkit",
-    "../store",
     "../widgets/_ComplexValueMixin",
     "dojo/_base/declare",
@@ -13,5 +12,5 @@
     "dojo/when",
     "dojo/text!./templates/question.html"
-], function(Content, Page, Router, Question, QuestionEditorPreview, QuestionEditorToolkit, store, _ComplexValueMixin, declare, event, lang, when, template) {
+], function(Content, Page, Router, questions, QuestionEditorPreview, QuestionEditorToolkit, _ComplexValueMixin, declare, event, lang, when, template) {
     return declare([Page,_ComplexValueMixin], {
         templateString: template,
@@ -43,7 +42,7 @@
             }
             if (this.questionId === "new") {
-                this.set('value', Question.create());
+                this.set('value', questions.create());
             } else {
-                when(store.get(this.questionId))
+                when(questions.load(this.questionId))
                 .then(lang.hitch(this, function(value) {
                     this.set('value', value);
@@ -54,5 +53,5 @@
             this.value = value;
             this.inherited(arguments);
-            this.titleNode.innerHTML = Question.DisplayTitle.get(value);
+            this.titleNode.innerHTML = value.title || "";
         },
         _getValueAttr: function() {
@@ -63,6 +62,5 @@
         _onSave: function(evt) {
             if ( this.validate() ) {
-                var value = this.get('value');
-                store.put(value)
+                questions.save(this.get('value'))
                 .then(function() {
                     Router.go('/questions');
Index: Dev/trunk/src/client/qed-client/pages/questions.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/questions.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/questions.js	(revision 487)
@@ -1,14 +1,14 @@
 define([
-    'dojo/_base/declare',
-    'dojo/_base/Deferred',
-    'dojo/_base/event',
-    'dojo/_base/lang',
-    '../store',
-    '../app/Content',
-    '../app/Router',
-    '../app/Page',
-    '../model/widgets/TabbedQuestionBrowser',
-    'dojo/text!./templates/questions.html'
-],function(declare,Deferred,event,lang,store,Content,Router,Page,TabbedQuestionBrowser,template) {
+    "../app/Content",
+    "../app/Page",
+    "../app/Router",
+    "../model/classes/questions",
+    "../model/widgets/TabbedQuestionBrowser",
+    "dojo/_base/Deferred",
+    "dojo/_base/declare",
+    "dojo/_base/event",
+    "dojo/_base/lang",
+    "dojo/text!./templates/questions.html"
+], function(Content, Page, Router, questions, TabbedQuestionBrowser, Deferred, declare, event, lang, template) {
     return declare([Page],{
         templateString: template,
@@ -44,5 +44,5 @@
         },
         onDeleteQuestion: function(question) {
-            store.remove(store.getIdentity(question),store.getRevision(question))
+            questions.remove(question)
             .then(function(){
                 Content.notify("Question deleted.");
@@ -55,6 +55,6 @@
         },
         onPublishQuestion: function(question) {
-            question.publicationDate = store.timestamp();
-            store.put(question)
+            question.publicationDate = new Date();
+            questions.save(question)
             .then(function(){
                 Content.notify("Question published.");
Index: Dev/trunk/src/client/qed-client/pages/response.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/response.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/response.js	(revision 487)
@@ -3,8 +3,5 @@
     "../app/Page",
     "../lib/async",
-    "../model/classes/Response",
-    "../model/classes/Survey",
-    "../model/classes/SurveyRun",
-    "../store",
+    "../model/classes/responses",
     "dojo/_base/declare",
     "dojo/_base/event",
@@ -16,5 +13,5 @@
     "require",
     "dojo/text!./templates/response.html"
-], function(Content, Page, async, Response, Survey, SurveyRun, store, declare, event, json, lang, all, request, when, require, template) {
+], function(Content, Page, async, responses, declare, event, json, lang, all, request, when, require, template) {
     return declare([Page],{
         contextRequire: require,
@@ -28,35 +25,17 @@
             this.inherited(arguments);
             this._disableSubmit();
-            var surveyRunId = this.surveyRunId;
-            var responseId = this.options && this.options.id;
-            if ( surveyRunId && responseId ) {
-                this._loadSurveyAndResponse(surveyRunId,responseId)
-                .then(lang.hitch(this, function() {
-                    if ( this.response.publicationDate ) {
-                        this._showInfo("<div>You already submitted your survey and cannot change it anymore. You can still view your answers here.</div>");
-                        this._disableSubmit();
-                    } else {
-                        this._enableSubmit();
-                    }
-                }), lang.hitch(this,function() {
-                    this._showInfo("<div>The url seems to be incorrect, no survey found.</div>");
-                }));
+            if ( !this.response ) {
+                this._showInfo("<div>The url seems to be incorrect, no response found.</div>");
             } else {
-                throw new Error("No valid uid or survey passed!");
+                this.titleNode.innerHTML = this.response._surveyRun.survey.title || "";
+                this.surveyWidget.set('survey', this.response._surveyRun.survey);
+                this.surveyWidget.set('value', this.response.answers || {});
+                if ( this.response.publicationDate ) {
+                    this._showInfo("<div>You already submitted your survey and cannot change it anymore. You can still view your answers here.</div>");
+                    this._disableSubmit();
+                } else {
+                    this._enableSubmit();
+                }
             }
-        },
-        _loadSurveyAndResponse: function(surveyRunId,responseId){
-            return all([request.get('/api/surveyRuns/'+surveyRunId,{handleAs:'json'}),
-                        request.get('/api/responses/'+responseId,{handleAs:'json'})])
-            .then(lang.hitch(this,function(surveyAndResponse){
-                var surveyRun = surveyAndResponse[0];
-                this.response = surveyAndResponse[1];
-                if ( this.response.surveyRunId !== surveyRunId ) {
-                    throw "Survey does not match the response...";
-                }
-                this.titleNode.innerHTML = Survey.DisplayTitle.get(surveyRun.survey);
-                this.surveyWidget.set('survey', surveyRun.survey);
-                this.surveyWidget.set('value', this.response.answers || {});
-            }));
         },
         _enableSubmit: function() {
@@ -78,10 +57,7 @@
             var answers = this.surveyWidget.get('value');
             this.response.answers = answers;
-            return request.put('/api/responses/'+store.getIdentity(this.response),{
-                handleAs:'json',
-                data:json.toJson(this.response),
-                headers:{"Content-Type": "application/json"}
-            }).then(lang.hitch(this,function(res){
-                this.response._rev = res.rev;
+            return responses.putWithSecret(this.response,this.response.secret)
+            .then(lang.hitch(this,function(response){
+                this.response = response;
                 Content.notify("Your response is saved.");
             }), function(err){
@@ -90,5 +66,5 @@
         },
         _onSubmit: function(e) {
-            this.response.publicationDate = store.timestamp();
+            this.response.publicationDate = new Date();
             this._getAnswersAndSaveResponse()
             .then(lang.hitch(this,function(){
@@ -110,10 +86,6 @@
             this._disableSubmit();
             this.surveyWidget.destroy();
-            request('/api/responses/'+store.getIdentity(this.response)+'?rev='+store.getRevision(this.response),{
-                method: 'DELETE',
-                handleAs:'json',
-                data:json.toJson(this.response),
-                headers:{"Content-Type": "application/json"}
-            }).then(lang.hitch(this,function(res){
+            responses.removeWithSecret(this.response,this.response.secret)
+            .then(lang.hitch(this,function(res){
                 this._showInfo("<div>Your response has been deleted, no answers have been saved.</div>");
                 Content.notify("Your response is deleted.");
Index: Dev/trunk/src/client/qed-client/pages/session.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/session.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/session.js	(revision 487)
@@ -1,4 +1,4 @@
 define([
-    'dojo/_base/array',
+    /*'dojo/_base/array',
     'dojo/_base/declare',
     'dojo/_base/event',
@@ -12,7 +12,7 @@
     '../model/classes/SessionTemplate',
     '../model/widgets/AccountListView',
-    'dojo/text!./templates/session.html'
+    'dojo/text!./templates/session.html'*/
 ],function(array,declare,event,lang,when,search,store,Page,Router,ThresholdFilteringSelect,SessionTemplate,AccountListView,template){
-    return declare([Page],{
+    /*return declare([Page],{
         templateString: template,
         session: null,
@@ -92,5 +92,5 @@
 
 
-    });
+    });*/
 });
 
Index: Dev/trunk/src/client/qed-client/pages/sessions.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/sessions.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/sessions.js	(revision 487)
@@ -1,4 +1,4 @@
 define([
-    'dojo/_base/declare',
+    /*'dojo/_base/declare',
     'dojo/_base/lang',
     'dojo/date/stamp',
@@ -7,7 +7,7 @@
     '../app/Page',
     '../widgets/ObjectBox',
-    'dojo/text!./templates/sessions.html'
+    'dojo/text!./templates/sessions.html'*/
 ],function(declare,lang,dateStamp,store,Router,Page,ObjectBox,template){
-    return declare([Page],{
+    /*return declare([Page],{
         templateString: template,
         templateActions: null,
@@ -18,8 +18,8 @@
             this.templateActions = {
                 "Edit": function(obj){
-                    Router.go('/session/'+store.getIdentity(obj));
+                    Router.go('/session/'+obj.get('id'));
                 },
                 "Delete": lang.hitch(this,function(obj){
-                    store.remove(store.getIdentity(obj),store.getRevision(obj))
+                    obj.remove()
                     .then(lang.hitch(this,function(){
                         this._refresh();
@@ -30,8 +30,8 @@
             this.sessionActions = {
                 "Facilitate": function(obj){
-                    Router.go('run',{uid:store.getIdentity(obj)});
+                    Router.go('run',{uid: obj.get('id')});
                 },
                 "Delete": lang.hitch(this,function(obj){
-                    store.remove(store.getIdentity(obj),store.getRevision(obj))
+                    obj.remove()
                     .then(lang.hitch(this,function(){
                         this._refresh();
@@ -48,4 +48,5 @@
         },
         _refreshByType: function(type,container,actions) {
+            // FIXME
             store.query("_design/default/_view/by_type",{key:type})
             .forEach(lang.hitch(this,function(obj){
@@ -61,4 +62,5 @@
         },
         _publishSession: function(sessionTemplate) {
+            // FIXME
             var session = lang.clone(sessionTemplate);
             delete session[store.idProperty];
@@ -73,4 +75,4 @@
             }));
         }
-    });
+    });*/
 });
Index: Dev/trunk/src/client/qed-client/pages/survey.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/survey.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/survey.js	(revision 487)
@@ -2,8 +2,7 @@
     "../app/Page",
     "../app/Router",
-    "../model/classes/Survey",
+    "../model/classes/surveys",
     "../model/widgets/QuestionListView",
     "../model/widgets/TabbedQuestionBrowser",
-    "../store",
     "dojo/_base/array",
     "dojo/_base/declare",
@@ -13,5 +12,5 @@
     "require",
     "dojo/text!./templates/survey.html"
-], function(Page, Router, Survey, QuestionListView, TabbedQuestionBrowser, store, array, declare, event, lang, when, require, template) {
+], function(Page, Router, surveys, QuestionListView, TabbedQuestionBrowser, array, declare, event, lang, when, require, template) {
     return declare([Page],{
         contextRequire: require,
@@ -63,12 +62,12 @@
         _loadSurvey: function() {
             if ( this.surveyId === "new" ) {
-                this.survey = Survey.create();
+                this.survey = surveys.create();
                 this.refresh();
             } else {
-                when(store.get(this.surveyId))
+                when(surveys.load(this.surveyId))
                 .then(lang.hitch(this,function(survey){
                     this.survey = survey;
                     this.questionList.set('value',
-                                          Survey.Questions.get(this.survey));
+                                          this.survey.questions);
                     this.refresh();
                 }));
@@ -79,5 +78,5 @@
         },
         refresh: function() {
-            this.titleNode.innerHTML = Survey.DisplayTitle.get(this.survey) || "(set title in properties)";
+            this.titleNode.innerHTML = this.survey.title || "(set title in properties)";
             this.propertiesDialog.set('value',this.survey);
         },
@@ -100,5 +99,5 @@
         _onSave: function(evt) {
             this.survey.questions = this.questionList.get('value');
-            store.put(this.survey)
+            surveys.save(this.survey)
             .then(function() { 
                 Router.go('/surveys');
@@ -111,5 +110,5 @@
         },
         _onShowPreview: function() {
-            Router.go('/previewSurvey/'+store.getIdentity(this.survey),{
+            Router.go('/previewSurvey/'+this.survey._id,{
                 preview: true
             });
Index: Dev/trunk/src/client/qed-client/pages/surveyRun.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/surveyRun.js	(revision 487)
@@ -4,7 +4,8 @@
     "../app/Router",
     "../lib/func",
-    "../model/classes/SurveyRun",
-    "../store",
+    "../model/classes/responses",
+    "../model/classes/surveyRuns",
     "../widgets/LineWithActionsWidget",
+    "dojo/_base/array",
     "dojo/_base/declare",
     "dojo/_base/event",
@@ -13,5 +14,5 @@
     "require",
     "dojo/text!./templates/surveyRun.html"
-], function(Content, Page, Router, func, SurveyRun, store, LineWithActionsWidget, declare, event, lang, when, require, template) {
+], function(Content, Page, Router, func, responses, surveyRuns, LineWithActionsWidget, array, declare, event, lang, when, require, template) {
     return declare([Page],{
         contextRequire: require,
@@ -24,5 +25,4 @@
             if ( this.surveyRunId ) {
                 this._loadSurveyRun();
-                this._loadResponses();
             } else {
                 throw "No valid uid or survey passed!";
@@ -30,41 +30,44 @@
         },
         _loadSurveyRun: function() {
-            when(store.get(this.surveyRunId))
+            when(surveyRuns.load(this.surveyRunId))
             .then(lang.hitch(this,function(surveyRun){
                 this.surveyRun = surveyRun;
                 this.refreshSurveyRun();
+                this._loadResponses();
             }));
         },
         refreshSurveyRun: function() {
-            this.titleNode.innerHTML = SurveyRun.DisplayTitle.get(this.surveyRun);
-            this.surveySummaryWidget.set('value',SurveyRun.Survey.get(this.surveyRun));
+            this.titleNode.innerHTML = this.surveyRun.title || "";
+            this.surveySummaryWidget.set('value',this.surveyRun.survey);
             this.surveyRunWidget.set('value',this.surveyRun);
             this._onPropChange();
         },
         _loadResponses: function() {
-            when(store.query("_design/responses/_view/by_surveyrun",{key:this.surveyRunId}))
-            .forEach(lang.hitch(this,function(response){
-                var actions = {
-                    view: {
-                        callback: function(){},
-                        properties: {
-                            title: "View response"
-                        }
-                    }
-                };
-                if ( !response.publicationDate ) {
-                    actions.remove = {
-                        callback: function(){},
-                        properties: {
-                            title: "Remove response"
+            responses.query({surveyRunId:surveyRuns.getId(this.surveyRun)})
+            .then(lang.hitch(this,function(allResponses){
+                array.forEach(allResponses, function(response){
+                    var actions = {
+                        view: {
+                            callback: function(){},
+                            properties: {
+                                title: "View response"
+                            }
                         }
                     };
-                }
-                var w = new LineWithActionsWidget({
-                    actions: actions
-                });
-                var responseId = store.getIdentity(response);
-                w.set('title',this._link(this._getResponseURL(this.surveyRunId,responseId),responseId));
-                w.placeAt(this.responsesNode);
+                    if ( !response.publicationDate ) {
+                        actions.remove = {
+                            callback: function(){},
+                            properties: {
+                                title: "Remove response"
+                            }
+                        };
+                    }
+                    var w = new LineWithActionsWidget({
+                        actions: actions
+                    });
+                    var rid = responses.getId(response);
+                    w.set('title',this._link(this._buildResponseURL(response),rid),rid);
+                    w.placeAt(this.responsesNode);
+                }, this);
             }));
         },
@@ -73,5 +76,5 @@
             if ( surveyRun.mode === "open" ) {
                 this.runURLNode.innerHTML =
-                    this._link(this._getGeneralURL(store.getIdentity(this.surveyRun)));
+                    this._link(this._buildGeneralURL(this.surveyRun));
             } else {
                 this.runURLNode.innerHTML =
@@ -79,9 +82,9 @@
             }
         },
-        _getGeneralURL: function(surveyRunId) {
-            return 'response.html#!/'+surveyRunId;
+        _buildGeneralURL: function(surveyRun) {
+            return 'response.html#!/surveyRuns/'+surveyRuns.getId(surveyRun)+'!secret='+surveyRun.secret;
         },
-        _getResponseURL: function(surveyRunId,responseId) {
-            return 'response.html#!/'+surveyRunId+'!id='+responseId;
+        _buildResponseURL: function(response) {
+            return 'response.html#!/responses/'+responses.getId(response)+'!secret='+response.secret;
         },
         _link: function(url,label) {
@@ -92,10 +95,5 @@
                 lang.mixin(this.surveyRun,this.surveyRunWidget.get('value'));
 
-                var SD = SurveyRun.StartDate;
-                var ED = SurveyRun.EndDate;
-                SD.set(this.surveyRun, SD.get(this.surveyRun));
-                ED.set(this.surveyRun, ED.get(this.surveyRun));
-
-                store.put(this.surveyRun)
+                surveyRuns.save(this.surveyRun)
                 .then(function() { 
                     Router.go('/surveys');
Index: Dev/trunk/src/client/qed-client/pages/surveys.js
===================================================================
--- Dev/trunk/src/client/qed-client/pages/surveys.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/pages/surveys.js	(revision 487)
@@ -1,16 +1,15 @@
 define([
-    'dojo/_base/array',
-    'dojo/_base/declare',
-    'dojo/_base/lang',
-    'dojo/when',
-    '../store',
-    '../app/Content',
-    '../app/Page',
-    '../app/Router',
-    '../model/classes/Survey',
-    '../model/classes/SurveyRun',
-    '../widgets/LineWithActionsWidget',
-    'dojo/text!./templates/surveys.html'
-],function(array,declare,lang,when,store,Content,Page,Router,Survey,SurveyRun,LineWithActionsWidget,template){
+    "../app/Content",
+    "../app/Page",
+    "../app/Router",
+    "../model/classes/surveys",
+    "../model/classes/surveyRuns",
+    "../widgets/LineWithActionsWidget",
+    "dojo/_base/array",
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/when",
+    "dojo/text!./templates/surveys.html"
+], function(Content, Page, Router, surveys, surveyRuns, LineWithActionsWidget, array, declare, lang, when, template) {
     return declare([Page],{
         templateString: template,
@@ -25,6 +24,7 @@
         _onPublishSurvey:function(survey){
             var self = this;
-            survey.publicationDate = store.timestamp();
-            store.put(survey).then(function(){
+            survey.publicationDate = new Date();
+            surveys.save(survey)
+            .then(function(){
                 self.refreshDrafts();
                 self.refreshPublished();
@@ -35,5 +35,5 @@
         _onDeleteSurvey:function(survey){
             var self = this;
-            store.remove(store.getIdentity(survey),store.getRevision(survey))
+            surveys.remove(survey)
             .then(function(){
                 self.refreshDrafts();
@@ -43,13 +43,13 @@
         },
         _onEditSurvey:function(survey){
-            Router.go('/survey/'+store.getIdentity(survey));
+            Router.go('/survey/'+survey._id);
         },
         _onPreviewSurvey:function(survey){
-            Router.go('/previewSurvey/'+store.getIdentity(survey));
+            Router.go('/previewSurvey/'+survey._id);
         },
         _onRunSurvey:function(survey){
-            var surveyRun = SurveyRun.create();
-            SurveyRun.Survey.set(surveyRun,survey);
-            store.put(surveyRun)
+            var surveyRun = surveyRuns.create();
+            surveyRun.survey = survey;
+            surveyRuns.save(surveyRun)
             .then(lang.hitch(this,function(surveyRun){
                 this._onRunDetails(surveyRun);
@@ -59,5 +59,5 @@
         },
         _onRunDetails: function(surveyRun) {
-            Router.go('/surveyRun/'+store.getIdentity(surveyRun));
+            Router.go('/surveyRun/'+surveyRun._id);
         },
         refresh: function() {
@@ -68,10 +68,9 @@
         refreshDrafts: function() {
             this.draftsContainer.set('content','');
-            when(store.query("_design/surveys/_view/drafts"),
-                    lang.hitch(this,function(surveys) {
+            when(surveys.query({drafts:true}), lang.hitch(this,function(surveys) {
                 this.draftsTab.set('title','Drafts ('+surveys.length+')');
                 array.forEach(surveys,function(survey){
                     var w = new LineWithActionsWidget({
-                        title: Survey.DisplayTitle.get(survey) || '(unnamed)',
+                        title: survey.title || '(unnamed)',
                         actions: [{
                             callback: lang.hitch(this,'_onPublishSurvey',survey),
@@ -110,10 +109,9 @@
         refreshPublished: function() {
             this.publishedContainer.set('content','');
-            when(store.query("_design/surveys/_view/published"),
-                    lang.hitch(this, function(surveys) {
+            when(surveys.query({published:true}), lang.hitch(this, function(surveys) {
                 this.publishedTab.set('title','Published ('+surveys.length+')');
                 array.forEach(surveys,function(survey){
                     var w = new LineWithActionsWidget({
-                        title: Survey.DisplayTitle.get(survey),
+                        title: survey.title || "",
                         actions:[{
                             callback: lang.hitch(this,'_onPreviewSurvey',survey),
@@ -138,10 +136,9 @@
         refreshRuns: function() {
             this.runsContainer.set('content','');
-            when(store.query("_design/default/_view/by_type",{key:'SurveyRun'}),
-                    lang.hitch(this,function(surveyRuns){
+            when(surveyRuns.query(), lang.hitch(this,function(surveyRuns){
                 this.runsTab.set('title','Runs ('+surveyRuns.length+')');
                 array.forEach(surveyRuns,function(surveyRun){
                     var w = new LineWithActionsWidget({
-                        title: SurveyRun.DisplayTitle.get(surveyRun),
+                        title: surveyRun.title || "",
                         actions:[{
                             callback: lang.hitch(this,'_onRunDetails',surveyRun),
Index: Dev/trunk/src/client/qed-client/request.js
===================================================================
--- Dev/trunk/src/client/qed-client/request.js	(revision 485)
+++ 	(revision )
@@ -1,68 +1,0 @@
-define([
-    "./session",
-    "dojo/Deferred",
-    "dojo/on",
-    "dojo/request"
-], function(session, Deferred, on, request) {
-
-    var user = session.get();
-    var queue = [];
-    
-    on(session, 'change', function(newUser) {
-        user = newUser;
-        if ( user ) {
-            retry();
-        }
-    });
-    
-    function retry() {
-        if (queue.length > 0) {
-            var item = queue.shift();
-            console.log("Retry",item.url);
-            real_request(item);
-        }
-    }
-    
-    function real_request(item) {
-        var req = request(item.url,item.options);
-
-        // forward successfull response
-        req.then(function(body){
-            item.dfd.resolve(body);
-        });
-
-        // handle unauthenticated and queued requests
-        req.response.then(function(response){
-            retry();
-        }, function(error) {
-            if ( error.response.status === 401 ) {
-                queue.unshift(item);
-                session.restore();
-            } else {
-                item.dfd.reject(error); // this should be error body
-                                        // not, the request?
-                retry();
-            }
-        });
-    }
-    
-    var _request = function(url, options) {
-        var item = {
-            url: url,
-            options: options,
-            dfd: new Deferred()
-        };
-        // only do the request directly if we are authenticated and
-        // there are no earlier requests queued.
-        if ( user && queue.length === 0 ) {
-            console.log("Request",url);
-            real_request(item);
-        } else {
-            console.log("Push",url);
-            queue.push(item);
-        }
-        return item.dfd.promise;
-    };
-
-    return _request;
-});
Index: Dev/trunk/src/client/qed-client/response.js
===================================================================
--- Dev/trunk/src/client/qed-client/response.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/response.js	(revision 487)
@@ -4,8 +4,7 @@
     "./app/Path",
     "./lib/async",
-    "./model/classes/Response",
-    "./model/classes/SurveyRun",
+    "./model/classes/responses",
+    "./model/classes/surveyRuns",
     "./pages/response",
-    "./store",
     "dojo/_base/json",
     "dojo/date",
@@ -16,5 +15,5 @@
     "./stddeps",
     "dojo/domReady!"
-], function(Content, Page, Path, async, Response, SurveyRun, ResponsePage, store, json, date, locale, hash, parser, request) {
+], function(Content, Page, Path, async, responses, surveyRuns, ResponsePage, json, date, locale, hash, parser, request) {
     parser.parse();
     Content.startup();
@@ -26,63 +25,27 @@
     }
 
-    var path = new Path('/:surveyRunId');
+    var path = new Path('/:type/:id');
     var params = path.match(hash());
     params.options = params.options || {};
-
-    if ( !params || !params.surveyRunId ) {
+    
+    if ( params && params.type === 'surveyRuns' ) {
+        var response = responses.create();
+        response.surveyRunId = params.id;
+        responses.postWithSecret(response,params.options.secret)
+        .then(setContent,function(err){ error(err.error); });
+    } else if ( params && params.type === 'responses' ) {
+        responses.getWithSecret(params.id,params.options.secret)
+        .then(setContent,function(err){ error(err.error); });
+    } else {
         error("Something is wrong with the URL, don't know what survey to show you. Sorry.");
-        return;
     }
 
-    var surveyRunId = params.surveyRunId;
-
-    function checkDates(surveyRun) {
-        var now = new Date();
-        var startDate = SurveyRun.StartDate.get(surveyRun);
-        var endDate = SurveyRun.EndDate.get(surveyRun);
-        if ( startDate && date.compare(startDate,now) > 0 ) {
-            error("This survey will start on "+locale.format(startDate,'date'));
-            throw false;
-        }
-        if ( endDate && date.compare(now,endDate) > 0 ) {
-            error("This survey ended on "+locale.format(endDate,'date'));
-            throw false;
-        }
+    function setContent(response) {
+        hash(Path.format("/responses/"+responses.getId(response),
+                         {secret:response.secret}));
+        Content.set(new ResponsePage({
+            response: response
+        }));
     }
 
-    request.get('/api/surveyRuns/'+surveyRunId,{handleAs:'json'})
-    .then(function(surveyRun){
-        checkDates(surveyRun);
-        if ( params.options.id ) {
-            return params.options.id;
-        } else {
-            if ( surveyRun.mode === "open") {
-                var response = Response.create();
-                response.surveyRunId = surveyRunId;
-                return request.post('/api/responses',{
-                    handleAs:'json',
-                    data:json.toJson(response),
-                    headers:{"Content-Type": "application/json"}
-                }).then(function(res){
-                    return res.id;
-                });
-            } else {
-                error("Cannot respond to closed survey without response id. Sorry.");
-                throw false;
-            }
-        }
-        return surveyRun;
-    },function(){
-        error("No running survey found for the given id. Sorry.");
-        throw false;
-    })
-    .then(function(responseId){
-        hash(Path.format("/"+surveyRunId,{ id: responseId }));
-        Content.set(new ResponsePage({
-            surveyRunId: surveyRunId,
-            options: {
-                id: responseId
-            }
-        }));
-    });
 });
Index: Dev/trunk/src/client/qed-client/routes.js
===================================================================
--- Dev/trunk/src/client/qed-client/routes.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/routes.js	(revision 487)
@@ -1,13 +1,11 @@
 define([
-    './pages/index',
-    './pages/questions',
-    './pages/question',
-    './pages/surveys',
-    './pages/survey',
-    './pages/surveyRun',
-    './pages/sessions',
-    './pages/session',
-    './pages/previewSurvey'
-],function(index,questions,question,surveys,survey,surveyRun,sessions,session,previewSurvey){
+    "./pages/index",
+    "./pages/previewSurvey",
+    "./pages/question",
+    "./pages/questions",
+    "./pages/survey",
+    "./pages/surveyRun",
+    "./pages/surveys"
+], function(index, previewSurvey, question, questions, survey, surveyRun, surveys) {
 
     return [
Index: Dev/trunk/src/client/qed-client/session.coffee
===================================================================
--- Dev/trunk/src/client/qed-client/session.coffee	(revision 485)
+++ Dev/trunk/src/client/qed-client/session.coffee	(revision 487)
@@ -2,7 +2,8 @@
     "dojo/_base/declare",
     "dojo/_base/json",
+    "dojo/Deferred",
     "dojo/Evented",
     "dojo/request"
-], (declare, json, Evented, request) ->
+], (declare, json, Deferred, Evented, request) ->
     Session = declare [Evented],
         info: null
@@ -18,5 +19,5 @@
                 @_set res
             , () =>
-                throw (@_set null)
+                new Deferred().reject (@_set null)
 
         login: (username, password) ->
@@ -30,5 +31,5 @@
                 @_set res
             , () =>
-                throw (@_set null)
+                new Deferred().reject (@_set null)
 
         logout: () ->
@@ -45,5 +46,5 @@
                 @info = newInfo
                 @emit 'change', @info
-                @info
+            @info
 
     new Session()
Index: Dev/trunk/src/client/qed-client/stddeps.js
===================================================================
--- Dev/trunk/src/client/qed-client/stddeps.js	(revision 485)
+++ Dev/trunk/src/client/qed-client/stddeps.js	(revision 487)
@@ -1,3 +1,4 @@
 define([
+
     // dijit & rft widgets used declaratively in templates
     'dijit/Dialog',
@@ -43,3 +44,4 @@
     './widgets/Selector',
     './widgets/TitleGroup'
+
 ],function(){});
Index: Dev/trunk/src/client/qed-client/store.js
===================================================================
--- Dev/trunk/src/client/qed-client/store.js	(revision 485)
+++ 	(revision )
@@ -1,47 +1,0 @@
-define([
-    'dojo/date/stamp',
-    'dojo/store/Cache',
-    'dojo/store/Memory',
-    'dojox/json/schema',
-    './model/schema',
-    './request',
-    './store/CouchStore'
-],function(stamp,Cache,Memory,jsonSchema,schema,request,CouchStore){
-    
-    var couchStore = new CouchStore({
-        target: '/data/',
-        request: request /*,
-        validate: function(object) {
-            var result = jsonSchema.validate(object,schema);
-            if ( result.valid ) {
-                return true;
-            } else {
-                console.log("Found error ",result," for invalid object ",object);
-                return false;
-            }
-        }*/
-    });
-    var memoryStore = new Memory({
-        idProperty: couchStore.idProperty
-    });
-    var cacheStore = new Cache(couchStore,memoryStore,{
-        isLoaded: function(object) {
-            // Unfortunately we cannot determine of the full documents were
-            // loaded or not. Therefore never cache query results.
-            return false;
-        }
-    });
-
-    var store = cacheStore;
-    store.formatDate = function(date){
-        return stamp.toISOString(date,{zulu:true});
-    };
-    store.parseDate = function(dateString){
-        return stamp.fromISOString(dateString);
-    };
-    store.timestamp = function() {
-        return this.formatDate(new Date());
-    };
-    return store;
-
-});
Index: Dev/trunk/src/client/qed-client/store/JsonRest.js
===================================================================
--- Dev/trunk/src/client/qed-client/store/JsonRest.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/store/JsonRest.js	(revision 487)
@@ -0,0 +1,198 @@
+define(["../xhr", "dojo/_base/lang", "dojo/json", "dojo/io-query", "dojo/_base/declare", "dojo/store/util/QueryResults" /*=====, "./api/Store" =====*/
+], function(xhr, lang, JSON, ioQuery, declare, queryResults /*=====, Store =====*/){
+
+    // No base class, but for purposes of documentation, the base class is dojo/store/api/Store
+    var base = null;
+    /*===== base = Store; =====*/
+
+    /*=====
+    var __HeaderOptions = {
+            // headers: Object?
+            //        Additional headers to send along with the request.
+        },
+        __PutDirectives = declare(Store.PutDirectives, __HeaderOptions),
+        __QueryOptions = declare(Store.QueryOptions, __HeaderOptions);
+    =====*/
+
+    return declare("dojo.store.JsonRest", base, {
+        // summary:
+        //        This is a basic store for RESTful communicating with a server through JSON
+        //        formatted data. It implements dojo/store/api/Store.
+
+        constructor: function(options){
+            // summary:
+            //        This is a basic store for RESTful communicating with a server through JSON
+            //        formatted data.
+            // options: dojo/store/JsonRest
+            //        This provides any configuration information that will be mixed into the store
+            this.headers = {};
+            declare.safeMixin(this, options);
+        },
+
+        // headers: Object
+        //        Additional headers to pass in all requests to the server. These can be overridden
+        //        by passing additional headers to calls to the store.
+        headers: {},
+
+        // target: String
+        //        The target base URL to use for all requests to the server. This string will be
+        //        prepended to the id to generate the URL (relative or absolute) for requests
+        //        sent to the server
+        target: "",
+
+        // idProperty: String
+        //        Indicates the property to use as the identity property. The values of this
+        //        property should be unique.
+        idProperty: "id",
+
+        // sortParam: String
+        //        The query parameter to used for holding sort information. If this is omitted, than
+        //        the sort information is included in a functional query token to avoid colliding
+        //        with the set of name/value pairs.
+
+        // ascendingPrefix: String
+        //        The prefix to apply to sort attribute names that are ascending
+        ascendingPrefix: "+",
+
+        // descendingPrefix: String
+        //        The prefix to apply to sort attribute names that are ascending
+        descendingPrefix: "-",
+
+
+        get: function(id, options){
+            // summary:
+            //        Retrieves an object by its identity. This will trigger a GET request to the server using
+            //        the url `this.target + id`.
+            // id: Number
+            //        The identity to use to lookup the object
+            // options: Object?
+            //        HTTP headers. For consistency with other methods, if a `headers` key exists on this object, it will be
+            //        used to provide HTTP headers instead.
+            // returns: Object
+            //        The object in the store that matches the given id.
+            options = options || {};
+            var headers = lang.mixin({ Accept: this.accepts }, this.headers, options.headers || options);
+            return xhr("GET", {
+                url: this.target + id, 
+                handleAs: "json",
+                headers: headers
+            });
+        },
+
+        // accepts: String
+        //        Defines the Accept header to use on HTTP requests
+        accepts: "application/javascript, application/json",
+
+        getIdentity: function(object){
+            // summary:
+            //        Returns an object's identity
+            // object: Object
+            //        The object to get the identity from
+            // returns: Number
+            return object[this.idProperty];
+        },
+
+        put: function(object, options){
+            // summary:
+            //        Stores an object. This will trigger a PUT request to the server
+            //        if the object has an id, otherwise it will trigger a POST request.
+            // object: Object
+            //        The object to store.
+            // options: __PutDirectives?
+            //        Additional metadata for storing the data.  Includes an "id"
+            //        property if a specific id is to be used.
+            // returns: dojo/_base/Deferred
+            options = options || {};
+            var id = ("id" in options) ? options.id : this.getIdentity(object);
+            var hasId = typeof id !== "undefined";
+            return xhr(hasId && !options.incremental ? "PUT" : "POST", {
+                url: hasId ? this.target + id : this.target,
+                postData: JSON.stringify(object),
+                handleAs: "json",
+                headers: lang.mixin({
+                    "Content-Type": "application/json",
+                    Accept: this.accepts,
+                    "If-Match": options.overwrite === true ? "*" : null,
+                    "If-None-Match": options.overwrite === false ? "*" : null
+                }, this.headers, options.headers)
+            });
+        },
+
+        add: function(object, options){
+            // summary:
+            //        Adds an object. This will trigger a PUT request to the server
+            //        if the object has an id, otherwise it will trigger a POST request.
+            // object: Object
+            //        The object to store.
+            // options: __PutDirectives?
+            //        Additional metadata for storing the data.  Includes an "id"
+            //        property if a specific id is to be used.
+            options = options || {};
+            options.overwrite = false;
+            return this.put(object, options);
+        },
+
+        remove: function(id, options){
+            // summary:
+            //        Deletes an object by its identity. This will trigger a DELETE request to the server.
+            // id: Number
+            //        The identity to use to delete the object
+            // options: __HeaderOptions?
+            //        HTTP headers.
+            options = options || {};
+            return xhr("DELETE", {
+                url: this.target + id,
+                headers: lang.mixin({}, this.headers, options.headers)
+            });
+        },
+
+        query: function(query, options){
+            // summary:
+            //        Queries the store for objects. This will trigger a GET request to the server, with the
+            //        query added as a query string.
+            // query: Object
+            //        The query to use for retrieving objects from the store.
+            // options: __QueryOptions?
+            //        The optional arguments to apply to the resultset.
+            // returns: dojo/store/api/Store.QueryResults
+            //        The results of the query, extended with iterative methods.
+            options = options || {};
+
+            var headers = lang.mixin({ Accept: this.accepts }, this.headers, options.headers);
+
+            if(options.start >= 0 || options.count >= 0){
+                //set X-Range for Opera since it blocks "Range" header
+                headers.Range = headers["X-Range"] = "items=" + (options.start || '0') + '-' +
+                    (("count" in options && options.count !== Infinity) ?
+                        (options.count + (options.start || 0) - 1) : '');
+            }
+            var hasQuestionMark = this.target.indexOf("?") > -1;
+            if(query && typeof query === "object"){
+                query = ioQuery.objectToQuery(query);
+                query = query ? (hasQuestionMark ? "&" : "?") + query: "";
+            }
+            if(options && options.sort){
+                var sortParam = this.sortParam;
+                query += (query || hasQuestionMark ? "&" : "?") + (sortParam ? sortParam + '=' : "sort(");
+                for(var i = 0; i<options.sort.length; i++){
+                    var sort = options.sort[i];
+                    query += (i > 0 ? "," : "") + (sort.descending ? this.descendingPrefix : this.ascendingPrefix) + encodeURIComponent(sort.attribute);
+                }
+                if(!sortParam){
+                    query += ")";
+                }
+            }
+            var results = xhr("GET", {
+                url: this.target + (query || ""),
+                handleAs: "json",
+                headers: headers
+            });
+            results.total = results.then(function(){
+                var range = results.ioArgs.xhr.getResponseHeader("Content-Range");
+                return range && (range = range.match(/\/(.*)/)) && +range[1];
+            });
+            return queryResults(results);
+        }
+    });
+
+});
Index: Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee
===================================================================
--- Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee	(revision 485)
+++ Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee	(revision 487)
@@ -17,5 +17,5 @@
             if @_started then return
             @inherited arguments
-            _on session, 'change', (lang.hitch @, @onUserChange)
+            _on session, 'change', (lang.hitch @, 'onUserChange')
             @onUserChange session.get()
         onLogin: (evt) ->
@@ -35,2 +35,3 @@
             else
                 @loginDialog.show()
+            null
Index: Dev/trunk/src/client/qed-client/xhr.js
===================================================================
--- Dev/trunk/src/client/qed-client/xhr.js	(revision 487)
+++ Dev/trunk/src/client/qed-client/xhr.js	(revision 487)
@@ -0,0 +1,65 @@
+define([
+    "./session",
+    "dojo/Deferred",
+    "dojo/_base/lang",
+    "dojo/on",
+    "dojo/_base/xhr"
+], function(session, Deferred, lang, on, xhr) {
+
+    var user = session.get();
+    var queue = [];
+    
+    on(session, 'change', function(newUser){
+        user = newUser;
+        retry();
+    });
+
+    function retry() {
+        if (user && queue.length > 0) {
+            var item = queue.shift();
+            console.log("Retry",item.options.url);
+            real_request(item);
+        }
+    }
+    
+    function real_request(item) {
+        var req = xhr(item.method,lang.mixin(item.options||{},{
+            failOk: true
+        }));
+        item.promise.ioArgs = req.ioArgs;
+
+        req.then(function(result){
+            item.dfd.resolve(result);
+            retry();
+        }, function(error){
+            if ( error.response.status === 401 ) {
+                queue.unshift(item);
+                session.restore();
+            } else {
+                item.dfd.reject(error);
+                retry();
+            }
+        });
+    }
+    
+    var _request = function(method, options) {
+        var item = {
+            method: method,
+            options: options,
+            dfd: new Deferred()
+        };
+        item.promise = lang.delegate(item.dfd.promise);
+        // only do the request directly if we are authenticated and
+        // there are no earlier requests queued.
+        if ( user && queue.length === 0 ) {
+            console.log("Request",options.url);
+            real_request(item);
+        } else {
+            console.log("Push",options.url);
+            queue.push(item);
+        }
+        return item.promise;
+    };
+
+    return _request;
+});
