Home Contact Projects

enterprise: Strawman ProposalDraft

A friend (Michael Zhang) and I may be working on a web framework for Rust, enterprise. This post serves as a strawman proposal for this framework, and as documentation for what the framework may eventually be.

Also note that despite the authorial "we," this is almost entirely my vision (hence the S-expressions, use of Prolog, etc.), so expect this to be a strawman that's lit aflame rather than fortified.

Introduction

The model we use for webapps is described by a dependency diagram:

dependency graph BLogic Business Logic Actions Actions BLogic->Actions Schema Schema BLogic->Schema Authentication Authentication BLogic->Authentication Actions->Schema Views Views Views->Schema ViewAdapters View Adapters Views->ViewAdapters Views->Authentication Authorization Authorization Authorization->Actions Authorization->Schema Authorization->Authentication

As well as a dataflow diagram for server-side rendering:

dataflow graph HTTP HTTP Router Router HTTP->Router Databases Databases and External Services DAL DAL Databases->DAL Authorization Authorization Actions Actions Authorization->Actions BLogic Business Logic Actions->BLogic Actions->DAL BLogic->Actions Views Views BLogic->Views DAL->Databases DAL->Authorization DAL->Actions Router->HTTP Router->BLogic Authentication Authentication Router->Authentication ViewAdapters View Adapters ViewAdapters->Router Views->ViewAdapters Authentication->Authorization Authentication->BLogic

In the above diagrams, yellow components are provided by enterprise, blue components are written by the application author in Rust, and pink components are written by the application author in a DSL.

The Schema and DAL components are taken from Ted Kaminski's "Stateless MVC," which describes them in detail.

Schema

The Schema component contains type declarations for each of the "domain objects." If a type ends up being sent over the network, it should probably be declared here. Derive macros are provided to allow the Router to validate these values.

The only exports of the Schema should be types -- if you find yourself exporting functions, they probably belong in the business logic.

Actions

Actions are the atomic primitive functions that are used to define the business logic. Macros are available to define CRUD actions for types in the Schema (relative to some data store supported by the DAL).

Business Logic

The Business Logic module transforms requests into data that can be handled directly by a View.

Views

Views are written in a React-like DSL.

View Adapters

View Adapters are backends for Views -- one exists to translate to HTML, another to translate to JSON, and another that performs tree-diffing to efficiently update HTML.

Auth

The generic phrase "auth" confusingly can refer to either "authentication" or "authorization." These are conflated both by the term and in many people's heads, so we avoid it, and make a strong split between the two.

Authentication

Authentication is the answer to the question "what user does this request correspond to?" As with other parts of a web application, enterprise simplifies authentication by abstracting it heavily.

For our app, we want to allow a plethora of authentication methods, while also allowing a user to have multiple authentication methods. (This is useful since a user might forget whether they registered with their Google account or email, and it allows an anonymous user to add an email and stop being anonymous!)

In app.sexp:

(authentication
  (multiple true)
  (providers
    anonymous-cookie
    (email-password :reset email)
    oauth-facebook
    oauth-google
    oauth-twitter))

In views/login.sexp:

TODO

Authorization

Authorization is the answer to the question "can this user perform this action?" This is almost entirely application-specific, so we leave the logic here to the app author.

But wait, we're using logic on a question with a boolean answer? Well, I know the best way to do this! enterprise apps specify authorization information with a Prolog dialect.

For our app, TODO.

In src/authorization.pro:

authorized(UserID, Action). # TODO
Comments are not enabled on this post.