User Journey: Sign up

Table of Contents

This page documents a user journey: A person registers themselves when the tenant allows self-registration.

A user journey describes what one person is trying to do, before anything is built. It is a design document that outlives any sprint, so it names the screens, the entity fields each screen shows, and the operations and messages each step needs.

1. Goal

"I have no account and I want one." The person registers a username, an email address and a password, and the system creates the account. The journey is done when the confirmation appears and the account exists.

The goal stops one step short of work. Registration creates an account; it does not give the person a place to work, and sign-in refuses an account with no party. So the honest end of this journey is a confirmation screen, not a workspace, and the person needs an administrator before the account is useful.

2. Actor and trigger

A person with no account, on a tenant whose settings allow self-registration. The trigger is the Sign up link on the sign-in screen, or an invitation saying the tenant accepts registrations. It starts when they open the sign-up screen and ends when the account is created.

This journey belongs to the person, not to an administrator: nobody is acting on somebody else's record. The administrator's version of "bring a person in" is Bring someone in, and it creates a usable account in one go.

One gate stands in front: the system flag system.user_signups. When it is off, registration is refused and the journey never starts. A second flag, system.signup_requires_authorization, is meant to gate registration on an approval step; no approval workflow exists, and the sign-up service refuses registration outright when that flag is on.

3. Steps

  1. Open sign-up. The person follows the Sign up link from the door. The system shows the tenant it is serving, and a form with username, email, password and confirmation. It decides from system.user_signups whether the form or a closed notice is the right answer.
  2. Enter the details. The person supplies a username, an email address and a password. The screen states the password rules so the person can satisfy them before submitting; nothing about the tenant's policy is a surprise.
  3. Submit. The system checks that sign-ups are enabled, that the username is free, that the email address is well formed and unused, and that the password meets the policy. Each refusal is a sentence the person can act on: sign-ups closed, username taken, email already registered, password too weak.
  4. The account is created. The server writes an account of type user with the username, the email address and the password material, and seeds its login record — no failed attempts, not locked, no reset required. It writes no contact record and no profile.
  5. The baseline role is granted. The server assigns the Viewer role to the new account. This is the only thing the account gains beyond existing, and it is the floor every account starts from.
  6. Nothing else is granted. No party association is created. No reporting line is drawn. No contact details, photo or job title exist. The account is a name with a password.
  7. Confirmation. The system confirms the account was created and returns the person to the door. It does not sign them in, and it cannot: the party check would refuse the session anyway.
  8. The account cannot sign in. At the door, the credential check succeeds and the party check fails. The reply is Account has no party assignment. Please contact your administrator. The gap does not appear on the sign-up screen; it appears here.

The journey carries no state the server has to keep: there is nothing to resume. The only artefact is the account row, and it waits for an administrator.

4. Screens and wireframes

One screen. The form, the refusal messages and the statement of what the new account receives are panels of that screen, because the last panel is the answer to the question the person will have next: what did I just get?

wireframe_sign_up.png

Figure 1: Sign up: the registration form, the refusals, and what the new account does and does not get.

The panel that carries the weight is the last one. It says plainly that the account has no party and no profile, and that an account with no party is refused at sign-in. A screen that hides that would send the person back to the door to fail.

5. Entities composed

Entity What it contributes Model
account The username and email the person chose, and the password material the server keeps ores.iam.account
account_type The new account is type user; the type decides whether password sign-in is offered at all ores.iam.account_type
login_info The security state seeded at registration: no failed attempts, not locked, no reset required ores.iam.login_info
account_party The association that is not created — and whose absence is the refusal at the door ores.iam.account_party
role The Viewer baseline the server grants, and the only access the account holds ores.iam.role

The password the person typed is never stored, only its hash, and the hash is not sent back. The screen shows the account id at most; nothing else about the account is readable by the caller.

6. Operations and messages

Step Operation Subject Status
Open sign-up Ask whether the deployment is provisioned iam.v1.ops.bootstrap_status exists
Open sign-up Read the deployment's registration policy, which decides whether a form is offered at all iam.v1.ops.registration_policy exists
Submit Create the account, its login record and its baseline role iam.v1.ops.signup exists
Refusals Say which refusal it is signup_response.error_code exists
The account cannot sign in Refuse an account that works in no party carried by iam.v1.ops.login exists
Fix it Give the new account a party iam.v1.account_parties.put partial

iam.v1.ops.signup comes from ores.iam.signup_messages: the request carries principal, password, email and hostname, and the response carries success, message, error_code, account_id, account_status, party_id and role_id. It is one of the few subjects that needs no session, because it is what a person without a session uses. iam.v1.ops.registration_policy comes from ores.iam.registration_policy_messages, and iam.v1.ops.bootstrap_status from ores.iam.login_messages.

partial on iam.v1.account_parties.put means the junction subject exists — the junction model renders it — but it carries iam::account_parties:write, a tenant-administrator permission. The new member cannot give themselves the party they need, which is the point: the fix is somebody else's action.

7. What is missing

The door itself is built. The policy read answers, the BFF serves GET /api/registration-policy and POST /api/signup, the wire client reaches both, and the screen renders the closed notice or the rail and states which of the two accounts a registration produced. Three things it still waits on.

  1. Nothing releases a waiting account. A tenant that nominates no default party produces a pending account, and the person is told so. What does not exist is the administrator's side: nothing lists the pending accounts and nothing gives one its first party. The requirement is stated in Registration and Onboarding Defaults and the screen belongs to Directory journeys.
  2. The approval flag closes the door rather than gating it. system.signup_requires_authorization is read, and a deployment that sets it is refused with signup_requires_authorization and told why: the door says so rather than pretending an approval happened. No approval workflow exists, and it is a workflow in ores.workflow rather than part of the door.
  3. No confirmation reaches the person. Registration answers the caller and nothing else: no email, no verification link, and no notice to an administrator that somebody is waiting. A person can register and nobody in the tenant learns of it, which is the sharper half of the gap above. The candidate is a notification on account creation, and an email-verification step if the tenant wants one.

8. Related journeys

  • Sign in — the next thing this person does, and where the missing party surfaces as a refusal.
  • Bring someone in — the administrator's path that creates a usable account in one step, party and initial role included.
  • New party — where the place a new account needs is created, when the tenant has nowhere to put them yet.
  • Shape the role catalogue — where the role a new account should start with is decided, since Viewer is currently granted without a choice.
  • First run — where a deployment with no account at all creates its first one, which is the other way accounts come into being.
  • Ask for more access — how the member asks for a role beyond the default one registration gave them, once the confirmation has been read.

9. Related knowledge

10. See also

Emacs 29.3 (Org mode 9.6.15)