Docs
  • 0.1.0latest

The admin console

How operators reach a company's console, the session it opens, and the rules every change follows: a role, a reason, an idempotency key, a typed confirmation where a change is wide, and masked addresses.

Each company has an admin console at <ADMIN_URL>/admin/<company>/, served by the binary on its own listener and origin, apart from the issuers. It holds no token, only a session cookie, and asks its API for everything it shows. It offers the sections the operator's roles can use: Users, Groups, Clients, Operators, Sign-in policy, Branding, Mail, Signing keys, Audit trail, and Companies in the system console. The API refuses the rest whatever is offered.

Signing in to the console

An operator opens <ADMIN_URL>/admin/<company>/signin, which sends the browser to that company's own sign-in as the client admin-console, with PKCE, a state and a nonce. Every company has this client registered with no grant type, so nothing outside the server can redeem its codes, and its consent page is always shown. The return to <ADMIN_URL>/admin/<company>/callback opens a console session only when:

  • the state, the issuer, the code and its nonce all check out;
  • the operator signed in with two factors;
  • they hold at least one current operator role.

Any other return gets one and the same refusal and is recorded.

The console session

The session is an HttpOnly, SameSite=Strict cookie (__Host- and Secure over https). It lasts at most 8 hours, ends after 30 minutes unused, and ends with the company sign-in session it came from or when the operator's last role is taken away. GET <ADMIN_URL>/admin/<company>/api/me names the operator and their roles; POST <ADMIN_URL>/admin/<company>/signout ends the session. Console requests are counted per client address under the sign-in limit.

Operator roles

Roles are held per company and per task:

RoleLets an operator
usersread and open accounts, issue enrolment codes, reveal an address, disable and enable accounts, manage groups
clientsregister and remove clients
policychange the two-factor and registration policy, branding and mail wording
keysrotate and withdraw signing keys
auditread the audit trail
companiescreate, suspend and resume companies; only system users hold it

Holding a role is what lets an operator give it (see Users, groups and operators).

How a change is made

  • It comes from the console's own origin as JSON carrying the operator's reason (1 to 500 characters) and an Idempotency-Key header (16 to 128 letters, digits, - or _).
  • It is made once per operator and key: sent again within a day it gets the first answer back, and the same key with another change is refused.
  • It is recorded as admin_action with the operator, the role, the change and the reason.
  • A change that replaces a policy or a stored value names the revision it read and is refused as changed_meanwhile when another change came first.
  • The page asks before a wide change: disabling an account names it and says what ends; removing a client says how many users hold a grant to it and asks for its id typed out; deleting a group says how many members it has; a two-factor policy change, a registration change or a company's suspension asks for the company id typed out; withdrawing a key asks for its id.

Lists page behind the server's cursor with no total, and an address is shown masked until it is revealed with a reason.

Sign-in policy

GET and PUT <ADMIN_URL>/admin/<company>/api/policy/two-factor (role policy) read and change the company's two-factor policy, off, optional or required; a change names the policy it replaces in expected. What each setting does to a sign-in is in Authorization and The account portal.

GET and PUT <ADMIN_URL>/admin/<company>/api/policy/registration read and change whether people may open their own account: {revision, open, domains, reason}, where domains lists up to 20 domains and an empty list means any address.

What it does not do yet

Stated as limits rather than promised: a change that reaches a whole company is made by one operator, with no second approval; the roles given by bootstrap-operator do not expire; a company made in the system console gets its first operator only through bootstrap-operator --company; and changing a client's registration is not in the console.