# First run: how S18 is built

What S18 built (plan CORE §3.24; TuteCampus's derived checklist and first-completion trail, TuteDesk's run-once,
hideable, by-permission steps, 25 October 2026; CORE-D18). The rules: **nothing is blocked**; **a step is done only
from real records**; **steps show by permission, never by role**; **the wizard writes only what the forms write**.

## Where it starts

A workspace comes from `CreateWorkspace`: the Service's New workspace, or self sign-up where it's on (`service.md`). Its `setup_at` is empty, so its Owner is offered the wizard once they've signed in and set up two-factor.

## The wizard (`SetupController`, `/setup/<step>`)

Offered by Home, once, to whoever may hand the workspace over (`workspace.ownership`), while `tenant.setup_at` is empty
(`Setup::offerWizard`); finishing or **Skip the rest** sets it (`Setup::finish`). Workspaces made before S18 are marked
set up by the migration; the factory makes set-up workspaces (`fresh()` for a new one). Each step saves through its
form's own action and remembers the next (`setup.next` in the session), so Home resumes there if a step sent the
person elsewhere first (sign-in's two-factor rule, S8, as soon as their role requires it).

| Step | Writes through | Also the form of |
|---|---|---|
| `workspace` | `UpdateWorkspace` (name, short name, legal name, `workspace_colour`, the logo through `FileIntake`) | Settings › This workspace |
| `region` | `UpdateRegion` (`country`, language, time zone, currency; the country's metadata fills the rest) | Settings › Regional |
| `signing_in` | `RoleEditor::twoFactor()` per role: those holding an elevated permission (and the account holder's), everyone, or none; step-up | the role page's toggle |
| `team` | `AddPerson`, `RoleEditor::assign` (the ceiling), `InvitePerson`, per row; errors on the row's field | Add a person, a person's roles, the invitation |
| `ready` | nothing: a summary | |

The idle timeout is shown, not asked: security controls are the platform's (handbook 3.3).

## The steps (`SetupStep`, `SetupSteps::ALL`, `Setup`)

| Step | Permission | Done when |
|---|---|---|
| `workspace` | `setting.manage` | the workspace has a short name, legal name, colour or logo |
| `region` | `setting.manage` | it has a currency |
| `signing_in` | `role.manage` | a role here requires two-factor by its own flag (the platform's `security.holder_two_factor` doesn't tick it) |
| `team` | `person.create` | someone besides the person setting up is here |

`Setup::steps()` gives the steps a person's permissions reach, each with `done()` and a line on where it stands, and
keeps each step's first completion once (`setup_event`: append-only, unique per workspace and step, kept for good);
`setup:record` (02:30) does the same for every workspace, so steps nobody looked at still count. The card on Home
(`SetupCard.vue`) is hidden per person and workspace (a `setup_hidden` row; a list in the person's preferences until plan SN D5); **Settings › Getting started** (`/setting/started`)
always lists the steps. "Set up two-factor yourself" isn't a step: sign-in asks for it at once (S8 has no grace), so it
could never wait on the card.

## This workspace, the chip

`tenant` gains `short_name` (the chip's letters; `initials` reads it first), `legal_name`, `colour`
(`workspace_colour`; the colours themselves are the brand layer's `brand.workspace_colours`), `country`,
`logo_file_id` and `setup_at`. The shared `tenant` prop carries the chip's colour and the logo (once stored), and
`WorkspaceChip` shows them. The logo's record is the workspace (`TenantPolicy::download`).

## The Service

The Workspaces list shows each workspace's progress (`setup_event` counted against the steps) and its last step; the
bell on a row (`platform.workspace.remind`, `workspace.remind`) sends `setup.reminder` to whoever may hand it over,
saying how many steps are left, audited (`setup.reminded`).

## Adding a step

1. A class extending `SetupStep`: `key()`, `icon()`, `permission()` (a catalogue key, or null for everyone), `done()`
   from records only, `href()`, optionally `detail()`; register it in `SetupSteps::ALL`.
2. Its words: `setup.step.<key>.title` and `.todo`.

## The guards

| Guard | Test |
|---|---|
| Each step ticks from its record, made through its own form; its first completion once | `Setup/SetupTest` |
| Steps by permission (a role with one permission sees one step); a Member sees none | `Setup/SetupTest` |
| The wizard offered once, to the Owner by permission; every step skippable; resumed after two-factor | `Setup/SetupTest` |
| The wizard writes what the forms write: their rules, the role ceiling, the invitation | `Setup/SetupTest` |
| Every step whole: its permission in the catalogue, its words | `Setup/SetupTest` |
| `setup_event` append-only and kept | `Setup/SetupTest`, `Guards/LogGuardTest` |
