Moss · the app server

Your app runs on the server.

Moss builds each person’s app on the server, from the screens and rows the charter grants them. The browser only draws it. So an assistant can work inside a person’s app through that person’s session, and it is given what they are given.

pnpm add @niscorp/moss @niscorp/charter @niscorp/nova @niscorp/prism @niscorp/strata @niscorp/tide @niscorp/vex zod · 0.8.2 · Apache-2.0

A running app is called a shell. Nova is at both ends of the socket: it runs your shell on the server, and draws it in the browser.

First steps →
Why Nisc needs it

You are sent only your app.

In Nisc the charter says which screens and which rows each person has. A browser cannot be trusted to keep to that, because whatever is sent to it can be read. So Moss builds each person’s app on the server, out of what they were granted, and sends the browser only what to draw.

The map

Where the pieces of Nisc meet.

Moss adds no language of its own. It puts the other packages to work, for one user at a time.

Charter decides once, at sign-in, and Moss enforces it twice: in the screens a shell is built from, and in every query Vex makes for it.

Cortex on Moss

Where an assistant runs.

An assistant has to run on a server, because its model key cannot go to a browser. On a usual server the user’s screen is not there. On Moss it is: the assistant is a function beside the user’s shell, and Moss hands it that user’s session.

Why a socket

Nobody asked, and the screen changed.

A web server answers when it is asked. An app on a server changes when nobody asked: somebody else wrote a row, or an assistant opened a screen. So Moss holds a socket to every shell.

The shell

Your app keeps running when you close the tab.

A shell runs in the server’s memory for as long as you are around. What has to last is saved to the database.

Restarting the server stops every app at once. Saved data is not affected.

What it costs

Every press is a round trip.

That is the price of running the app on the server, and Moss’s design document measures it. One connected person costs the server about this much memory:

The shell43 KB
The connection, with compression on260 KB

A changed screen is sent whole. With shellFrameDelta on, a change in place is sent as 1 to 4% of it. Typing does not wait for the server: a new screen never overwrites the input you are typing in.

Asked of an app server

What an engineer asks.

Do I need it for a website?Nonisc export draws every page at build, and any host serves the files. This site is served that way.
Can the first screen arrive with the page?YesrenderDocument reads the person’s screen off their shell, and your own components draw it into your page. The socket takes over from there.
Can I run more than one process?YesWith each person pinned to one process. A write on one process does not yet refresh screens on another.
Can I bring my own sign-in?Yessession can be your own function that says who a token is. Moss asks it at connect, and again every minute the socket lives.
Can a script in my page read the session?NoOn your app’s own page the browser keeps it in a cookie no script can read.
Does signing out reach every tab?Yessession.revoke() closes every connection that person has, and drops their shell.
Can a person’s roles change while they are connected?YesinvalidateIdentity builds their shell again, from what they are granted now.
Can two people get different versions of one screen?YesA layout variant is granted the way a screen is, and put in before the person’s shell is built.
Can every model call be recorded?YesDeclare runs. Moss stamps who asked and when, and you hand it the model and every turn.