Feature: Participants
1. Overview
- Goal: A participant is a person taking part in the event — the unit Registry counts, moves and displays on the live headcount. Staff register each person once, with a name, a birthday and an availability window, and mark them as registered (enrolled) or a guest (visitor). From there the dashboard derives who is present, splits majors from minors, and highlights today's birthdays, all without anyone maintaining a status by hand.
- Who uses it: All three roles register, read and edit participants;
PROJECT_ADMINISTRATORandPROJECT_COORDINATORadditionally review movement history, and onlyPROJECT_ADMINISTRATORcan permanently delete one. - Option required: None — always available. Participants are part of the core.
2. Roles & Permissions
Actions use CRUD shorthand — Create, Read, Update, Delete — plus History (view a participant's movement history). See Roles & Permissions and Domain Model → Participant.
| Role | Permitted actions | Conditions / Scope |
|---|---|---|
PROJECT_ADMINISTRATOR | C R U D + History | Only role that can permanently delete a participant — and only while that participant has no movement history (see §3); also registers, edits and views movement history (REGISTRY_...PARTICIPANT_C/R/U/D, REGISTRY_PROJECT_PARTICIPANT_HISTORY_R). |
PROJECT_COORDINATOR | C R U + History | Registers, edits, disables/enables and views movement history, same as the administrator — but cannot delete a participant. |
PROJECT_PARTICIPANT | C R U | Registers, reads, edits and disables/enables participants — same floor as the coordinator — but cannot delete one or view movement history. |
3. Business rules
firstNameandlastNameidentify the participant.birthdayis required and cannot be in the future (@PastOrPresent).- Availability window is optional. With no window of its own, a participant inherits their group's window (union across all groups they belong to, if several), falling back to the project's if that's also unset — see Domain Model → Availability windows. When both
startandendare set,startmust be beforeend(@StartBeforeEnd). When the participant defines no window, belongs to no group, and the project itself defines no window, there is nothing left to inherit and the participant is permanently available — until aDEFINITIVE_DEPARTUREmovement, which ends their participation for good independently of any window. - Type. Each participant is
REGISTEREDorGUEST. AREGISTEREDparticipant's normal state is present (they generateOUTmovements when leaving); aGUEST's normal state is off-site (they generateINmovements when arriving). See Domain Model → Participant. - Optional user link. A participant may or may not be linked to a real user account; most are not. Linking pre-fills the participant's name from the account and locks the name fields.
- Disabling is a soft, reversible action. A disabled participant is hidden but can be re-enabled.
- A participant with history cannot be deleted — by anyone. Once a participant appears in any movement, deleting them would rewrite the headcount history, so the request is refused for every role,
PROJECT_ADMINISTRATORincluded.DELETEexists only to remove a participant registered by mistake, before they have any movement. To take an active participant out of circulation, disable them (or record aDEFINITIVE_DEPARTURE). - Derived presence. Presence status (
IN/OUT/UNAVAILABLE) is computed from the participant's latest movement and their availability window — it is never set directly. With no movement yet recorded, the participant isOUT— not yet arrived — whatever their type. AREGISTEREDparticipant's "normal state is present" describes how movements are justified (leaving needs a reason, returning does not), not a presence the system assumes before the firstIN. - Derived age split. Major vs minor is computed from
birthday, driving the dashboard "majors vs minors" panel and the today's-birthdays panel.
4. Behavioral scenarios (BDD)
gherkin
Scenario: Check-in staff register a new participant
Given I am a PROJECT_PARTICIPANT on a project
When I register "Jordan Lee" born 2010-05-04 as a REGISTERED participant
Then the participant is created
And their normal state is "present" — leaving will later require a justification
And their derived presence is OUT until their first check-in — not yet arrivedgherkin
Scenario: A birthday in the future is rejected
Given I am registering a participant
When I set the birthday to a date after today
Then the request is rejected by the @PastOrPresent validator
And no participant is createdgherkin
Scenario: A missing birthday is rejected
Given I am registering a participant
When I submit without a birthday
Then the request is rejected because birthday is requiredgherkin
Scenario: The availability start must be before its end
Given I am registering a participant
When I set the availability start after its end
Then the request is rejected by the @StartBeforeEnd validatorgherkin
Scenario: Linking a participant to a user locks the name
Given I am editing a participant
When I link the participant to a user account
Then the first and last name are pre-filled from the account
And the name fields become read-onlygherkin
Scenario: A participant can edit a participant but not delete one
Given I am a PROJECT_PARTICIPANT on a project
And an existing participant "Jordan Lee"
When I correct Jordan Lee's birthday
Then the update is accepted
When I then attempt to delete Jordan Lee
Then the request is refused for lack of REGISTRY_PROJECT_PARTICIPANT_Dgherkin
Scenario: A coordinator cannot delete a participant either
Given I am a PROJECT_COORDINATOR on a project
And an existing participant "Jordan Lee"
When I attempt to delete Jordan Lee
Then the request is refused for lack of REGISTRY_PROJECT_PARTICIPANT_Dgherkin
Scenario: A participant who already has movement history cannot be deleted
Given I am the PROJECT_ADMINISTRATOR of a project
And a participant "Jordan Lee" who appears in at least one recorded movement
When I attempt to delete Jordan Lee
Then the request is refused to preserve the movement history
And disabling the participant is offered insteadgherkin
Scenario: A coordinator reviews a participant's movement history
Given I am a PROJECT_COORDINATOR on a project
When I open a participant's movement history
Then I see their past check-in and check-out movementsgherkin
Scenario: Today's-birthdays panel lists participants born on this day
Given several participants are registered with various birthdays
When the dashboard requests today's birthdays
Then it returns only the participants whose birthday falls on today's date5. API surface
The endpoints backing this feature — their paths, methods and the permission each one requires — are specified in Technical → API Reference, and kept there only so the transport contract never drifts from this spec. The authority for each action is in §2; the rules it must satisfy are in §3.