Skip to content

Access

An account’s role and grants decide which entities it can read and which actions it can perform. Roles are documents an administrator edits; grants apply to every entity or to a scope (a kind, a tag, a site, a set of ids). Your own account is Profile… in the Terminal menu, for every signed-in user; Users, Invites and Roles are the People group of Mainframe Settings…, Keys and Audit are under System, and Security is a part of System → Configuration, for administrators.

The card names the Mainframe (Sign in to SAB) and asks for an email and a password. Three things can follow:

Mainframe answers The card shows
A second factor is enrolled A six-digit code. Use a backup code swaps in a text field; Trust this device for 30 days skips the code on this browser until then
The password was set by an administrator A password change: the current (temporary) password, the new one twice. The console opens once it is changed
The security settings require a second factor this account has not enrolled The enrolment dialog, with sign-out as the only other way out
The account is disabled Account disabled

Continue with <label> appears when single sign-on is enabled. A wrong password reads Wrong email or password; too many attempts in the configured window read Too many attempts.

The Mainframe field is prefilled with this Terminal deployment’s default on a first visit. A link such as /login?mainframe=https%3A%2F%2Fmainframe.dev.mainline.inc prefills another destination. Hosted Terminal accepts HTTPS Mainframes beneath .mainline.inc, including nested hosts. Check the displayed hostname before entering credentials.

/login always shows the form, even when already signed in. It lists remembered Mainframes and checks which sessions remain valid; Continue opens an existing session. Unreachable and expired destinations remain available for retry or login.

Use Terminal → Switch Mainframe to choose another signed-in account, or Sign In to Mainframe… to add one. Each tab keeps its own connection through reloads. Switching leaves other Mainframe sessions valid; layouts, drafts and unread state belong to the selected Mainframe and account. This browser remembers account metadata; session cookies stay scoped to each Mainframe hostname.

Sign Out… asks which Mainframe/account to sign out of and affects only that Mainframe session. Passkeys have been removed; use password/TOTP or configured single sign-on.

Row Does
Name Editable; Save
Email, Role Read-only; an administrator changes them
Password Change…: current, new, confirm. Other sessions end; this one continues
Two-factor Enable…: the password, then a QR code and the secret for an authenticator app, then the six-digit check, then ten backup codes shown once with Copy. Disable… asks the password
Sessions Every open session with this device marked; Revoke per row, Revoke other sessions
Personal API keys Keys that act as you for scripts (Authorization: Bearer mf_user_…); New key names one and sets its expiry (the Security maximum applies); the value is shown once

The table lists every member: name, email, role (a select that applies at once), whether a second factor is enrolled, join time and original invite code (when present), the last sign-in, and the state (active, disabled, must change password). New user creates an account with a temporary password shown once, or with a password you type; the user changes it at the first sign-in. The row menu offers Reset password… (the same choice), Sessions… (revoke one or all), Grants… (a table of action × scope beyond the role), Disable / Enable, and Delete user… (typed confirmation of the email). Disabling, deleting, a role change, a grant change and a password reset end the user’s open connections at once; the last administrator cannot be demoted, disabled or deleted, and you cannot disable or delete yourself.

Open Mainframe Settings → Invites to create reusable, role-bound links. Creation defaults to field and Unlimited uses; choose a role and optionally set a whole-number limit. Administrator roles require an additional confirmation. Copy the link, show its QR code, or download SVG/PNG for printing or sharing. Anyone holding the link can register with that role while the invite is available.

Links and QR codes include ?mainframe=…, so a shared Terminal sends people to the Mainframe that issued the invite. Front 2.5.2 or newer uses the same target when scanning its QR or opening Open in Front; update older Front installs first. Existing invite codes keep working: copying their link again adds the target. Older links without the parameter still use their Terminal’s default Mainframe and cannot identify another instance on a shared Terminal.

The table shows code, label, role, successful uses, status, creator and creation time. Edit Limit… changes its label or cap; role is fixed. Retire Invite… permanently stops new registrations. Existing users keep access, deleted users do not return uses, and failed or repeated registration requests do not consume extra uses. Raising an exhausted invite’s cap makes it available again.

View Users filters the users table to that invite. Joined and Invite record membership creation and its source; they remain after retirement or role changes. Both visible views refresh periodically and when the window regains focus, so background API registrations appear without reopening Settings.

The public link displays workspace, role and availability. Clients register through the invite API with a name, email-format identifier and password, then use ordinary sign-in. Synthetic email addresses are accepted; username authentication is not added.

Cards for every role with its member and grant counts. admin is built in: it may do anything, its grants are read-only and it cannot be removed. A new Mainframe also starts with operator, field and observer (field is for people on the ground with Front: it sees everything an observer sees, talks and chats, marks and discusses the map, and captures, but commands nothing); they are ordinary roles, written once, to edit or remove like any other. A Mainframe that had them as built-ins makes them editable at its next start, with the current starting grants. Duplicate… starts a custom role from any role. New role and Edit… open the editor: name, description, the layout applied when a member signs in (None keeps their own arrangement; admin takes a layout too) and the grants table. The card shows the layout when one is set. Changing only the layout ends nobody’s session. A role held by members or referenced by a non-retired invite (including an exhausted invite) cannot be removed. A role edit applies to its members at once (their connections restart).

Module keys authenticate modules (radar-net, TAK, the simulator…). A key created at boot from the environment carries from env. Rotate creates a second enabled key for the same module, shown once: restart the module with the new value, then Revoke… the old one. Stream keys let cameras publish RTMP video. Personal keys are each user’s own, in Profile.

auth.* events (sign-ins with their outcome and address, sign-outs, second-factor and password changes), access.* events (every change above, with who did it) and settings.* events (every settings save with its diff). Filter by kind, by principal (a name or an id) and by range; Details shows the event’s data; Export CSV writes the loaded rows (at most 1000).

The security settings document: session age, the login rate limit, the password minimum length, the two-factor requirement (Off, Admins, Everyone; the row warns when no administrator has enrolled), single sign-on with its button label, and the personal key maximum age. Rows marked after restart apply at the next Mainframe start. Single sign-on also needs MAINFRAME_SSO_ISSUER, MAINFRAME_SSO_CLIENT_ID and MAINFRAME_SSO_CLIENT_SECRET in the environment; the row says whether they are set. A user the identity provider creates joins as an observer.

Layouts. layouts.customize lets a role arrange the workspace: the Panels, Layout and Plan menus, adding, closing, moving and floating panels, saving layouts. Without it Terminal stays in Fixed Layouts; with it, Unlock Layouts makes everything arrangeable. layouts.use decides which shared layouts the role sees, in the menu, as Alt+1… and as the layout applied at sign-in: a layout is matched as its id with kind layout, so layouts.use on ids (the picker lists them as layout · Pilot) names the layouts and all gives every one. The starting operator and observer roles use the seeded Pilot and Video Wall layouts in Fixed Layouts; field customizes; admin holds *. For operators who arrange panels, add both grants on all to the operator role (or to a duplicate of it).

Actions are entity.read, entity.telemetry.read, entity.video.read, entity.control, entity.manage, entity.command.<capability>, history.read, replay, docs.<collection>.read|write, system.admin, *, the four comms actions chat.read, chat.write, voice.listen and voice.talk, and the two layout actions layouts.customize and layouts.use. A scope is all, a kind, a tag, a site or a list of ids. Kinds and tags are the ones providers announce, so a tag-scoped grant is as trustworthy as the module that tags the entity. Grants from mainframe.config.ts show as config and are synced at every boot; grants written here survive restarts.

Chat groups and voice rooms are permissioned the same way, and the grant is the membership: nobody joins or leaves a group. A group is matched as its id with kind chat-group and the tags set in Mainframe Settings → Chat Rooms; a room as its id with kind voice-room. So chat.write on all writes in every group, on kind chat-group likewise, on a tag follows the groups carrying it, and on ids names the groups; the ids picker lists them as group · Ops and room · Team Alfa beside the entities, and the kind picker offers chat-group and voice-room. The starting operator and field roles hold all four actions on all; the observer reads chat and hears rooms; both read the group and room lists. A site scope never matches a group or a room. For voice, voice.listen joins a room and hears it and voice.talk publishes the microphone in it: the join token Mainframe mints carries exactly those two answers, and a role or grant change removes the user from every room at once so the next join reflects it (see Voice).