Part of #199 .
Goal
Define the durable domain contract that separates a room from the racing activity occurring inside it before changing persistence or socket behavior.
Required definitions
Room
A durable place people join. It owns:
name and stable public identifier/access code;
room kind, including normal and competition;
visibility and password/access policy;
lifecycle and retention state;
owner, administrator, and moderation state;
optional competition association.
RaceSession
A single stream of attempts for one event within a room. It owns:
room reference;
event ID;
format or race mode;
scramble source/stream;
scheduled and actual start/end times;
state such as pending, active, paused, ended, or canceled;
session-specific participant racing state.
Use RaceSession in code to avoid confusion with authentication sessions.
Behavioral invariants
Creating a normal room automatically creates its first active race session.
The existing Create room → copy link → friend joins → race flow does not gain another required step.
Changing events ends the active race session and creates another; it never deletes earlier attempts or solves.
A normal room exposes one active race session at a time.
A competition room may expose multiple race sessions.
Attempts belong to exactly one race session.
Solves belong to exactly one attempt and user.
Room membership/moderation state is separate from competing/waiting state.
Owner/admin semantics remain compatible with Stabilize room host ownership across rejoins #195 .
History and privacy rules can be enforced after a room or session is no longer active.
Decisions to record
Which presence state is durable in PostgreSQL versus transient in Redis.
Whether competition identity is a dedicated table or an external reference on Room.
Session state transitions and who may perform them.
Behavior for private, hidden, expired, deleted, and competition rooms.
Whether room administrators are automatically session administrators.
Stable identifiers exposed to clients and retained across migration.
Socket/API payload compatibility during rollout.
Deliverable
Add a concise architecture decision record or equivalent repository documentation, plus domain-level tests or fixtures that express the invariants.
Acceptance criteria
Non-goals
Implementing the database migration.
Building competition-room UI.
Designing friends, invitations, or notifications.
Part of #199.
Goal
Define the durable domain contract that separates a room from the racing activity occurring inside it before changing persistence or socket behavior.
Required definitions
Room
A durable place people join. It owns:
RaceSession
A single stream of attempts for one event within a room. It owns:
Use
RaceSessionin code to avoid confusion with authentication sessions.Behavioral invariants
Decisions to record
Deliverable
Add a concise architecture decision record or equivalent repository documentation, plus domain-level tests or fixtures that express the invariants.
Acceptance criteria
Non-goals