An organization, its applications and one login
An organization is one tenant: one SQLite file, one image directory, one address, one set of logins. An organization can hold more than one application, and each application answers under its own first path segment.
https://sampletown.matterdata.example/club/members/17 └─┬┘ the application's mountRead App mount for the declaration and its refusals.
One login, one role per application
Section titled “One login, one role per application”A login belongs to the organization. A role belongs to one application of it, so one person can be the treasurer in the club application and a reader in the calendar.
This decides what the reserved role authenticated means:
That reading holds whether the organization has one application or five. A rule whose meaning changed when somebody installed a second application would be a rule you cannot reason about.
A refusal is still attributed. Somebody denied a page of an application they hold no role in is anonymous for the access decision. The audit event still names them. Those are two different questions, and answering them with one value would give either a leak or an unattributable refusal.
What the applications of one organization share
Section titled “What the applications of one organization share”Everything in the list below is the organization’s, not an application’s.
| Shared | Consequence |
|---|---|
| the SQLite file and the image directory | one backup covers every application |
| the logins and their sessions | signing in once reaches every application |
| the CSRF token, the color scheme and the reader’s time zone | one browser cookie jar |
| the 512 MiB image quota | one application’s uploads use up another’s room |
| the audit log | one trail. An event of an application names it; a sign-in names none |
the administration page at /matterdata |
one door to the organization’s logins |
Each application keeps its own tables, roles, menu and hook modules. It also keeps its own
declared time zone, and its own value for an application-wide scope.
Table names do not collide. Two applications can each declare events, because the engine
stores a table under <application name>__<table name>. Your .mtd files, a ref(...), a
hook’s ctx.db.query(...) and every error message keep the short name.
The trust boundary is the organization, not the application
Section titled “The trust boundary is the organization, not the application”Two applications of one organization are one origin, and the session cookie carries
Path=/. A browser cannot keep them apart.
That sharing is the feature. It is also the boundary, and it decides one design question:
- Applications used by the same people → one organization. A club’s member register and its calendar. Everybody signs in once, and each application grants its own roles.
- A public site and an internal one → two organizations. Two tenants, two files, two addresses, two sessions. Nothing a mistake in one can reach in the other.
- Applications that share data → one application. A mount is an address, not a join. An application cannot read another application’s tables, and no hook can either.
How a person reaches an application
Section titled “How a person reaches an application”The address / of the organization lists the applications this person can open. Each entry
links to the first page of that application they may open, and names the role they hold there.
Three rules decide what happens at /:
- One application in the organization:
/redirects to it. The redirect is decided before the visitor is considered, so the address does not reveal who is asking. - Several applications:
/lists them. An application in which this person can open no page is left out, rather than shown and refused. - An application declares
mount: /: that application answers/, and there is no list. If it declares no page atroute: /, then/answers 404.
Nothing reads your data to build the list. It discloses that an application exists and what it is called, which its address already discloses to anybody who guesses it.
Every address the engine serves begins with /matterdata. Most of them stay at the
organization’s root, because they belong to the organization: /matterdata/login,
/matterdata/logout, /matterdata, /matterdata/appearance, /matterdata/timezone,
/matterdata/static/… and /matterdata/theme.css.
Two engine addresses belong to one application and sit under its mount, as
/<mount>/matterdata/…: scope, which switches an application-wide scope, and blob/…, which
serves an image. Both resolve a name against one application’s model, and at the organization’s
root that name would have two meanings.
What is not built yet
Section titled “What is not built yet”The frame draws no switcher between applications, and a root-relative link written in Markdown leaves the application it was written in. Read Project status before you plan an organization around several applications.