CloudWall core

CloudWall is a set of components, combined into a single design document by Ddoc Lab app, running inside CloudWall. So CloudWall builds itself.

Varying set of components and rules, one can build any type of CW-based system: from very relaxed developer stand — to a restricted data kiosk with a single bucket-’disk‘ attached, and only single app allowed.

CW is intended to run in browser with upfront unknown set of apps, so only bullet-proof technologies are used mostly. Also since dev things happen in browser tab, there’s no npm, babel, webpack and all that stuff. 

CloudWall runs nice in all modern browsers on all modern platforms, both desktop and mobile, however dev-related stuff can’t run properly on mobile devices.

To read this doc smoothly, please first install CloudWall and download its sources.

Client runtime

CloudWall client side architecture is layered, basically CW orchestrates layer interaction and serves as middleware between storage and apps, also starting and switching those apps. This part is compiled to /cw/cloudwall.js, which is imported from CW core Ddoc lab project.

CloudWall 2.4 runtime

‘GDI’ App runtime CloudWall Storage Renders HTML and receives user interactions Manages bindings between data and UI controls Prepares, runs and closes apps, manages app switch Stores apps and documents, optionally syncs with external CouchDB instances All CloudWall components run in a browser tab, no server or even internet connection required after system started. Any local DB can eventually sync with external CouchDB instances over http(s). One CouchDB can have several users connected, thus providing shared workspace, docs and applications set. CouchDB CouchDB

Before CloudWall session starts, CW runs cw.login() method, which is served as a separate script /cw/start-couch.js, to make authorization more flexible. The script is also imported from CW core Ddoc lab project, however may be changed in special builds (ie CloudWall for static hosting uses this feature to fake auth, because there‘s no CouchDB). 

CloudWall requires a lot of libs, which must start before CW. Absolutely required libs are served at start as /lib/general.js, less required — as /lib/plugins.js. Apps may require not yet loaded libs, and they may be served either from local doc, or from remote if absent in client’s browser.

Buckets as ‘disks’

Buckets export large API, which is basically extended and restricted PouchDB.

Buckets are named flat stores of CouchDB-style JSON docs, with JS map/reduce functionality. 

At a client side CloudWall reads user profile and creates several virtual API endpoints, buckets, pre-defined in profile. A bucket may be strictly remote, with no offline capabilities. Also a bucket may be local and sync with one or more remote CouchDBs, or with other local buckets.

Per-bucket sync settings are stored in user profile and are very fine-grain configurable. Sync may be uni- or bi-directional, filtered or restricted by doc _id-s list, intermittent or continuous.

Apps and components

CloudWall apps and components are JSONs of jquerymy manifest structure. If an app/component received from a bucket doc, the doc should have type:"manifest" and special doc _id.

Components cache

CW keeps separate sets of apps/components for each bucket. However, apps/components of system cw bucket, and apps pre-loaded and cached by ‹script›, are visible system-wide.

To see all system-wide available components, type $.my.cache() in browser console. Apps are also components, but not all components are apps — ie color picker or image cropper.

Classes of apps

Applications are divided into two classes: ‘just apps’ and editors. 

Editors are generally bound to a specific doc type, and can create, open, edit and save doc of that type. One editor app instance edits one doc at a time, however there can be many instances of one editor per bucket.

‘Just apps’ are not bound to any specific type, they do not edit docs, at least directly. There can be only one running instance of an app for a bucket. For example, bucket shell (list of docs) is ‘just app’.

Run and switch

CloudWall starts (or switches to) this or that app, reacting to URL hash change. After receiving something like #lab/Inliner/someDocId CW will try to start Inliner app in the lab bucket, and open doc with _id:"someDocId" from that bucket for editing.

Running apps are shown as tabs in navbar. Closing a tab closes the app, but editors ask for save if the doc was changed.

System components

Some apps and components are required for any CW-based project. Any build must have at least navbar and shell. Also builds with several buckets need a dashboard to switch between buckets, also some dialogs are needed, attachments manager, etc.

There is a list of components, generally present in any build:

Doc _idDescription
cw-Couch-Auth-0k00
CouchDB auth popup
cw-Sys-Dock-4vx1
CloudWall default backend navbar
cw-Sys-YesNoCancel-4vx1
System Yes / No / Cancel configurable dialog
cw-Sys-Confirm-4vx1
System confirm configurable dialog
cw-DB-Shell-3teg
Default bucket shell, list of docs 
cw-Sys-Hub-3teg
Default list of buckets, dashboard

Critical build components should be delivered using static ‹script› inclusion, not using replication. they should be present before cw.start call.

User profile and access rights

CloudWall requires its users to be authorized in this or that way. After user logs in, CW loads runtime config and user profile, which both determine how system will behave. Authorization is decoupled from core and is located in /cw/start-couch.js script.

Successful auth means CouchDB said Ok, and user profile was received. User profile is a JSON doc, has type:"settings" and contains list of user available buckets. Also profile contains secret crypto keys if any.

Profile JSON may come from two sources: it can be forcibly taken from remote on start, thus being non-writable, or be local and writable. Latter is good mode for admins and devs, former — for ordinary users.

Writable profiles are stored encrypted, that is why CW asks not only for CouchDB login/paswword on strt, but also asks for PIN. PIN is needed to decrypt profile.

Profile contains a list of user’s cryptokeys, buckets and their syncs, it doesn’t contain lists of allowed apps, doctypes, and actions. Access rights for particular apps and doc types are defined in runtime config, separately from user profile. 

Custom builds 

CloudWall is pretty small: CW core is ~60kb gzipped, minimal supporting JS scripts set adds ~140kb, CSS adds ~40kb.

Dev set of CloudWall has several samples of both relaxed and restricted CloudWall-based systems, as Ddoc Lab projects. All samples have a lot of comments inside and can be easily cloned, and then tuned to build a new project.

Generally, CW-based project includes static assets, CW config and profile generator, and a subset of apps. Critical applications and components are frozen and included as static assets; less critical apps may be delivered to a user as JSON manifest docs, via bucket sync. 

Ddoc Lab, the main build tool that includes own IDE, represents each target design ddoc as a source doc of type:"ddlab", which is then processed by Ddoc Lab build tool, which is of webpack complexity. Ddoc Lab ui of this site source project looks like this (click to zoom):

Ddoc Lab supports various formats and markup languages, understands JS and Erlang (in limited amount), tracks dependencies and globals, and proven to be very useful and reliable. Entire Cloudwall ecosystem is build using Ddoc Lab.

Deployment

CW has built-in app, Photon, which is very useful for re-starting deployment sync tasks. Photon can run both under CW environment and as a standalone.

Most CW-based projects, both as sources and when built, are basically sets of CouchDB docs (often 1–3 design documents when built). Apps being distributed using same replication flow as ordinary docs, have some unique advantages:

  • Deployment is zero pain, regardless how many nodes you have. Apps packed in design docs just sync to all nodes according to CouchDB _replicator sync topology.
  • Hot server code replacement: CouchDB (with Couchbox optionally) makes it perfect.
  • Easy rollback: on troubles previous version can be taken back in seconds, just take previous design doc revision.
  • Transactional-style static assets update: a node receives all static files attached to app simultaneously with the app itself.

CloudWall-based systems are especially well-suited for distributed mesh networks of CouchDB nodes: deployment is literally a single-click operation.

Isotopic CSS

CloudWall uses own CSS styling, derived from Atomic CSS and sharing its ideas, however bit simpler. Most frequently used props are defined as shortcuts, non-semantic ‘isotopes’.

Like class="mb10" adds margin-bottom:10px, and class="fl oh p5" is  float:left; overflow:hidden;  padding:5px, and so on.

Gradation is different, starting from 1px for smaller values.

All that rules, and also rules for UI plugins onboard, are contained in /css/general.css stylesheet. The stylesheet is built from CW general.css Ddoc Lab project, so may be cloned, tuned, re-built and re-included in custom build.

Security

Read more about crypto safe in Crypto API manual.

CouchDB key feature is ease of replication, which, from security POV, means data can easily leak. Insufficiently tested filter function, improper bucket security and handreds of other reason may cause leakage.

Having copy of data locally adds even more risks.

To ensure sensitive data can’t be read even on occasional unwanted replication, CloudWall has built-in crypto lib. It forces encryption of all sensitive user profile docs on save, and can be optionally applied to encrypt some user docs.

Advanced use

CloudWall plays especially well in part with Couchbox, which augments native CouchDB query server with hooks and API constructor. Since Couchbox, as native CouchDB, uses design documents for hosting code, entire Couchbox-based system may be developed right in the browser.

There are several examples of very successful use of this scenario.

Source code map

CloudWall core is built from several Ddoc Lab projects and manifests.

// here should be full list with annotation, to be written