Access rules

Which apps, protocols and networks each person may use, how long a sign-in lasts, and which apps may be signed in to at all.

With no access rules, anybody with the right password may use every protocol, from anywhere, with any app. A sign-in on the server’s pages lasts thirty days. An organisation’s access rules change that. They can say “no POP3”, “IMAP only from the office”, “finance only from our own networks” or “sign in again every eight hours”.

What the rules hold

Each organisation has one document of access rules:

PartWhat it says
networksThe networks the rules name, each with a name and its address ranges, its countries, or both.
rulesThe rules, read top to bottom. The first that matches decides.
otherwiseWhat happens to anything no rule decides: allow (the default) or refuse.
sessionHow long a sign-in lasts, and whether closing the browser ends it.
appsWhich apps may be signed in to at all.

An example:

{
  "networks": [
    { "name": "Office", "ranges": ["203.0.113.0/24", "2001:db8:1::/48"] }
  ],
  "rules": [
    { "who": "everybody", "what": ["pop3"], "from": ["anywhere"], "decision": "refuse",
      "note": "Nobody here uses POP3" },
    { "who": "group:finance@example.com", "what": ["everything"], "from": ["Office"], "decision": "allow" },
    { "who": "group:finance@example.com", "what": ["everything"], "from": ["anywhere"], "decision": "refuse" }
  ],
  "otherwise": "allow",
  "session": { "hours": 8, "endsWithBrowser": true },
  "apps": { "others": "listed", "listed": ["versealx-cli"] }
}

In this example nobody may use POP3. The finance group may use nothing from outside the office. Everybody else may use everything else from anywhere. A sign-in lasts eight hours, and closing the browser ends it. Besides Nixt Mail and the console, only the mail command line may be signed in to.

Networks

A network has a name, up to 64 characters, and its ranges. A range is written as 203.0.113.0/24 or 2001:db8:1::/48, or it is one address. The rules match the address a connection comes from. Behind a load balancer that speaks the PROXY protocol, that is the address the load balancer passes on. An organisation names at most 50 networks, with at most 500 ranges between them.

A network can also name countries, by their two-letter codes ("countries": ["DE", "AT"]), as the server’s built-in table places an address. With ranges as well, an address must be in one of the ranges and in one of the countries. A country is a hint, not proof, since a VPN or a journey moves it, so it can only narrow: a rule may refuse from a network that is only countries, but a rule that would allow from countries alone is refused when you save it.

Rules

Each rule has four parts, and an optional note of up to 200 characters for the next administrator:

FieldValues
whoeverybody, group: and a group’s address, domain: and one of the organisation’s domains, or account: and one person’s address.
whatAny of imap, pop3, submission, jmap, dav (CalDAV and CardDAV), managesieve and console (the console and the admin API behind it), app: and an app’s name, or everything.
fromanywhere, or the names of networks.
decisionallow or refuse.

The rules are read in order, and the first rule that matches who, what and where decides. Put the narrow rules above the broad ones. In the example, the finance group’s office rule must come before its refusal from anywhere. An organisation writes at most 100 rules.

The apps a rule can name:

AppName
Nixt Mailversealx-mail
The consoleversealx-console
The mail command lineversealx-cli
The server’s command line, signed in with --serverversealx-server-admin
A person’s own account pages: sessions, app passwords, encryption keys, quarantine, second step, recovery, forwarding, deleted mail, mailbox activity, calendars, and changing the passwordaccount-pages

How long a sign-in lasts

session.hours is how long a sign-in on the server’s pages lasts before the person signs in again, however often it is used. The default is 720 hours, thirty days, and the most is a year. It covers every token issued to that sign-in, whichever app holds them.

With session.endsWithBrowser set to true, a sign-in made in a web browser also ends when the browser stops using it. That happens once it has gone unused for longer than an access token lives, one hour, and a quarter of an hour more. This is what closing the browser does to it. A sign-in made by an app that is not a browser, such as Nixt Mail on a phone, is not affected.

A sign-in that has lasted too long, or whose browser has closed, is ended at its next refresh, and the person signs in again. Their sessions list says why; see See and end one session.

Which apps may be signed in to

apps.othersMeaning
allowedEvery app may be signed in to. The default.
listedOnly the apps in apps.listed, by name.
refusedNone of them.

Nixt Mail and the console may always be signed in to, whatever the list says.

What people are told

The rules are asked only after the password or token has been accepted. A wrong password is answered as always, so the rules never tell anybody whether an address exists. A refusal is not a failed sign-in: it never counts toward a lockout.

Each way in refuses in its own form, and mail apps show the words to the person:

Way inAnswer
IMAPNO [NOPERM] and the words
SMTP submission535 5.7.9 and the words
POP3-ERR [AUTH] and the words
ManageSieveNO and the words
JMAP, CalDAV and CardDAV403 and the words
The console and the admin API403, at every request
The sign-in pagesYour organisation does not allow signing in to this app, before anything is issued

The words name what is refused: Your organisation does not allow IMAP. When the person may use it from somewhere else, such as the office, the words add from this network, so they know where they are is the reason.

When a change takes effect

Every node reads the rules again within five seconds of a change, and a group’s members within a minute. Nobody needs to restart anything.

  • A new sign-in is decided by the new rules at once.
  • A connection that is already open is asked again at each command it sends, and every minute while it is idle. If the change refuses it, it is closed: IMAP and ManageSieve with BYE, POP3 with -ERR, and SMTP submission with 421 4.7.0.
  • An app’s token is refused at its next request. When the rules refuse a sign-in’s refresh, the sign-in ends, and the person’s sessions list says the access rules ended it.

Nobody locks the organisation out

A save is refused if the rules would refuse any of the organisation’s administrators the console from every network. The answer names the administrator, so the rules can be changed to let them in from somewhere first. Every active account that holds an administrative role counts, including helpdesks and auditors.

Simulate a sign-in

The access rules are one of several checks a sign-in goes through. To see all of them for one person, simulate a sign-in: give an address, what they sign in to, what they sign in with, the address they come from and, if you like, a moment. The server walks the sign-in through every check in the order it makes them and says which one decides:

  1. The account: the organisation is open, and the address belongs to an active person.
  2. Lockout: too many wrong passwords from the account or the network, at that moment.
  3. The credential: the password, an app password made for that protocol, a passkey, or the organisation’s single sign-on.
  4. Activation: an invitation that has not been accepted yet.
  5. A password to change: one an administrator asked them to change, or one found in a breach.
  6. Second step: whether one is asked of them. The mail apps cannot ask for one, so they sign in there with an app password.
  7. Passkeys: what the organisation allows, and how many the person has.
  8. Break-glass: a break-glass account is not refused by the rules on the sign-in page or in the console.
  9. Access rules: which rule decides, and the person’s plan.
  10. Location: no sign-in is decided by where it comes from, beyond the networks in the rules.

Each check says whether it lets them in, refuses, asks for more (a second step or a new password on the sign-in page), or is not checked, and why. A simulation changes nothing: no failed attempt is counted, nothing is added to the sign-ins list, and nobody is told.

Whoever may test the rules about the person’s domain may simulate their sign-in.

Who may change them

RoleMay
Administrator of the organisationChange all of it.
Domain administratorRead all of it, and change the rules whose who is one of their own domains, wherever those rules are in the list. Their rules may keep their people out of more than the organisation’s rules do, but never let them into more.
AuditorRead it.

Every save is a line in the audit log, with the rules before and after.

In the console

Access rules, under Sign-in and sync, is one form: the networks with their ranges and countries, the rules in the order they apply, what happens to anything else, how long a sign-in lasts, and which apps may be signed in to. Move a rule up or down to change its place. If something cannot be saved, the console says why at the box that is wrong. If somebody else saved first, it offers the rules as they are now.

Test, beside the form, asks whether somebody could use something from an address. It says which rule decides and what they would be told. The test reads the rules in the form, saved or not, so you can try a change before you save it.

Simulate a sign-in, below it, walks one person’s sign-in through every check and says which decides.

A domain administrator sees the organisation’s rules in their places, read-only, and changes their own domains’ rules. An auditor sees the rules as tables.

On the People page, the list of where people sign in from can also show the sign-ins the access rules refused. Each refusal is also in the audit log, once an hour for each person and door.

On the command line

See the rules in words:

vsx admin access show
Version 3, saved 2026-10-02 09:14 UTC by ada@example.com.
Networks:
  Office               203.0.113.0/24, 2001:db8:1::/48
Rules, the first that matches deciding:
    1. refuse everybody — pop3 — from anywhere  (Nobody here uses POP3)
    2. allow  group:finance@example.com — everything — from Office
    3. refuse group:finance@example.com — everything — from anywhere
Anything else, from anywhere: allowed.
A sign-in lasts 8 hours, and closing the browser ends one made in it.
Nixt Mail, the console and the mail command line may be signed in to, and no other app.

Change them in a file and save it:

vsx admin access show --json > access.json
vsx admin access set access.json

A file written by --json carries the version it was read at, and the save is refused if somebody else has saved since. A file that holds only a list is taken as the rules, and the rest is kept as it is.

Ask about one person before or after a change:

vsx admin access test ada@example.com imap 198.51.100.7
vsx admin access test ada@example.com app:versealx-cli 198.51.100.7 --file access.json
ada@example.com may not use imap from 198.51.100.7: rule 3 decides. They are told: Your organisation does not allow IMAP from this network.

Simulate a sign-in, now or at a moment in UTC:

vsx admin access simulate ada@example.com --way imap --credential password --from 198.51.100.7 --at 2026-10-01T03:00

It prints one line for each check, then what decides:

ada@example.com signing in over imap with password from 198.51.100.7 at 2026-10-01T03:00:00Z:
  second-step      refuses      an app password is what signs in
They do not sign in: second-step decides — an app password is what signs in.

--way takes imap, pop3, submission, jmap, dav, managesieve, console or app: and an app’s client id. --credential takes password, app-password, passkey or sso.

See who the rules refused with the right credentials in the last ninety days:

vsx admin org sign-ins --refused

Over the API

MethodPathPurpose
GET/api/v1/tenants/{tenant}/accessThe rules, with version, updatedAt and by. Version 0 means none have been written.
PUT/api/v1/tenants/{tenant}/accessSave the whole document, with the version you read. 409 if it has changed since. 400 if it cannot be applied, with a pointer to the part that is wrong, such as #/rules/2/from/0.
POST/api/v1/tenants/{tenant}/access/testBody: address, what and from, and optionally policy, a document not saved yet. The answer says whether they are allowed, what decides (by: rule, otherwise or apps, with the rule’s place from 0), and the words they would be told.
POST/api/v1/tenants/{tenant}/access/simulateBody: address, way, credential and from, and optionally at, a moment in UTC such as 2026-10-01T03:00:00Z or Unix milliseconds. The answer has steps, each with its check, outcome (passes, refuses, asks or not-checked) and why, and decides, the first step that refuses or signs in.
GET/api/v1/tenants/{tenant}/sign-ins?outcome=refusedThe sign-ins the rules refused.

Something unclear or out of date on this page? Tell us.