# Decisions Register

The single place where open business questions get answered and where technical
choices are recorded. Code that depends on an entry here must cite its ID.

- **D-n** (`D1`, `D2`, …) — decisions confirmed with the client. They override the BRD.
- **DEC-xx** — business questions raised by the BRD (gaps, conflicts, missing values).
- **TD-xx** — technical decisions made by the engineering team.
- **SCR-xx** — differences between the screens and the BRD, with their outcome.

**Statuses:** `Open` (no answer — stop and ask before building behavior that
depends on it) · `Partly resolved` (build what is decided; the remainder is a
setting or still open) · `Working assumption` (build with this, keep it
configurable) · `Resolved` (final) · `Proposed` (TD awaiting approval) ·
`Accepted` (TD in force) · `Superseded`.

> Agents: when you resolve or assume anything, update the row here (one short
> line — budget `docs.budgets.index_line_chars`) and add an entry to
> [DECISIONS_LOG.md](DECISIONS_LOG.md) with the detail. Never edit a
> resolved decision silently — supersede it with a new log entry.
> Allocate the next free ID first:
> `grep -oE "^\| (D|DEC|TD|SCR)-?[0-9]+" docs/DECISIONS.md | sort -t- -k2 -n | tail -3`

---

## Client-confirmed decisions

D1–D4 from the client's additional requirements (notes of 18-10-2026 and 22-10-2026); D5–D9 from the client's cancellation and settlement policy (10-11-2026, `C-§NN`). They override the main BRD where they conflict.

| ID | Decision | Overrides | Affects |
|----|----------|-----------|---------|
| D1 | Hall booking is separate from course creation: the trainer books a hall independently and types the venue (hall name, address, map link, notes) into the in-person course; the course form never searches halls or pulls bookings; the admin reviews the venue with the course (A-p.18–19). | BRD p.12, p.43 (pick hall from list), p.83 (link Booked request), p.119 (confirmed booking at review) | TRR-010, TRR-033, HPV-012, HPV-013, ADM-021, ADM-026 |
| D2 | Published-course edits: substantive edits (name, description, price, category, sessions, seats, learning points) are requested and re-reviewed while the approved version stays live; operational edits (session link) apply directly; no type change after confirmed enrollments; seats ≥ confirmed; cancellation only by admin approval of the owner's request (A-p.11–13). | BRD p.49–50 (any edit re-reviews; substantive edits made by the admin; no cancel) | TRR-020, TRR-021, TRR-023, ADM-028, ADM-031 |
| D3 | Training centers create and own courses: one create screen with "course provider" (center / affiliated trainer); a trainer's course (with proposed price) is reviewed, re-priced and submitted by the center; the center is the financial owner and receives payouts; center packages show under the center's name (A-p.16–18). | BRD p.63–65, p.70 (course created by the trainer; center never edits or submits) | CTR-007, CTR-008, CTR-009, CTR-010, CTR-012 |
| D4 | Course points are set by the admin during course review (the trainer cannot set them) and are earned when the course is completed (A-p.10–11). | BRD p.23, p.30 (points on enrolling), p.131 (points on purchase) | TRN-008, TRN-012, TRN-019, ADM-026, ADM-041 |
| D5 | Course cancellation: only an independent trainer or a center (its courses, incl. affiliated trainers') requests it with a reason; the admin approves / rejects; Cancelled only on approval; a started course only exceptionally; a Completed course never; no automatic cancellation at a passed deadline — the admin extends or cancels (C-§01–07, §24). | BRD p.50, A-p.13–14 | TRR-023, TRR-015, ADM-031, ADM-032 |
| D6 | Trainee enrollments: no self-cancel or refund request; an enrollment in a cancelled course stays in My courses as Cancelled with its refund status; cash is refunded outside the system via support; a refund is never marked done before the transfer is confirmed, never paid twice (C-§08–11). | BRD p.33, p.51, p.133 | TRN-013, TRN-014, ADM-031, ADM-033, ADM-034 |
| D7 | Money on cancellation: Pending entitlements cancelled; no points / cashback for a cancelled course, pending rewards cancelled, used points / cashback returned; only cash paid refunded; ticket kept, marked not valid; no certificate (C-§21–23). | BRD p.51, p.133 | TRN-019, TRN-024, TRN-025, TRR-025, ADM-038 |
| D8 | Hall bookings: the booker withdraws before Booked without approval; a Booked booking is cancelled by the provider — on the booker's request (fees not refunded, warned first) or offline-agreed with a reason; no in-system refund; never cancels a course (C-§12–15). | BR-HALL-16/17, BR-ADMIN-HALL-12/13 | TRR-032, HPV-011, ADM-020 |
| D9 | Packages and subscriptions: a package withdrawn from sale stays valid for buyers; a cancelled course inside a bought package leaves the package running, its share settled outside; the trainee cannot cancel a package; when a trainer subscription ends, live courses keep selling but no new course is created or published (C-§16–20). | BRD p.128, A-p.20 | TRN-017, TRR-016, ADM-013, TRR-030, ADM-037 |

## Business decisions (from the BRD)

Raised at BRD ingest (2026-11-11). Detail per row in [DECISIONS_LOG.md](DECISIONS_LOG.md). Page refs: `p.N` main BRD, `A-p.N` additional requirements.

| ID | Topic | Status | Decision / working assumption | Affects |
|----|-------|--------|-------------------------------|---------|
| DEC-01 | "Live sessions" in NFRs | Working assumption | No in-platform live sessions: external courses run outside through a link (p.17 vs §5.5). | PLT-*, TRR-011 |
| DEC-02 | OTP expiry and resend limits | Working assumption | BRD leaves them to the technical implementation: keep them in settings; values to be set by engineering (p.18). | TRN-002, TRN-005, TRN-022 |
| DEC-03 | Trainee "address" field | Resolved | Country + city from the lists + free-text address (project owner, 2026-11-12). | TRN-002, TRN-022, ADM-004 |
| DEC-04 | One person, several account types | Resolved | One account per app: each account has one type; the same mobile may hold accounts on different apps; mobile unique per account type (project owner, 2026-11-12). | TRN-002, TRR-002, TRR-003 |
| DEC-05 | Enrolling in a free course | Open | Free courses exist (p.42, p.123) but the enrollment flow has no free path: confirm directly, cashback / points / ticket rules? | TRN-010, TRN-012, TRR-009 |
| DEC-06 | Payment gateway vendor and methods | Open | Client contracts the provider (p.6); vendor, methods (mada, Apple Pay…), currency SAR assumed, refund support unknown. **Client (2026-11-12) accepted the deferral:** vendor stays open. **Integration is deferred** (client has not supplied the gateway yet): built behind the `PaymentGateway` contract with a `fake` driver (TD-15). | PLT-002, TRN-011, TRR-006 |
| DEC-07 | Stacking of offer, discount, cashback and points | Open | Only "offers are not combined" is stated (p.25); order and combination of course discount, package, cashback and points undefined. | TRN-010, TRR-013, TRN-019 |
| DEC-08 | Course discount controls | Resolved | No maximum, no separate approval: the trainer decides; the discount is reviewed with the course and a rejection sends it back to the trainer (project owner, 2026-11-12). | TRR-013, ADM-026 |
| DEC-09 | Package approval | Resolved | No package review; the owner and the admin can deactivate a package (project owner + C-§16, 2026-11-12). | TRR-016, CTR-012, ADM-013 |
| DEC-10 | Changing date, time or hall of a published course | Open | Main BRD: such edits are made by the admin (p.50); notes: controlled change with enrollee notice (A-p.12–13). Who approves and how? | TRR-021, ADM-028, TRN-024 |
| DEC-11 | Course end time and auto-completion | Open | How the end date/time is derived (duration unit, sessions) and whether completion is automatic by default or manual (A-p.20, p.122). | TRR-022, ADM-030 |
| DEC-12 | Enrollment cancellation and refunds | Resolved | No trainee request; the admin removes the trainee and adjusts the wallet; cash refunded outside via support, refund status tracked, never paid twice (project owner + D6, 2026-11-12). | TRN-021, ADM-031, TRR-025, PLT-002 |
| DEC-13 | Trainer profile edits after approval | Resolved | Only licence, IBAN and CV go back to admin review; other fields save directly (project owner, 2026-11-12). | TRR-028, ADM-006 |
| DEC-14 | Credentials for admin- or center-created accounts | Partly resolved | **Client (2026-11-12): login identifiers.** Admin dashboard = email + password; trainer, trainee, hall provider and training center = phone + password (supersedes the BRD/sprint "username" for center and provider, and "phone or email" for trainer). **Still open:** how the initial password is generated and the delivery channel (SMS / email). Build behind a notification contract; channel kept in settings. | CTR-005, ADM-010, ADM-015 |
| DEC-15 | Center financial model and payouts | Partly resolved | The center sees course revenue, platform income and net income per course and in total; rate source and payout method still open (project owner, 2026-11-12). | CTR-010, ADM-038 |
| DEC-16 | Center's own halls | Resolved | Out of scope: halls belong only to providers; a course venue is text, location link and photos (project owner, 2026-11-12). | CTR-016, ADM-011 |
| DEC-17 | Hall booking ↔ course link after D1 | Resolved | No link. An in-person course stores hall name, address, location link and photos; TRR-033, HPV-012, HPV-013 and course parts of ADM-021 / TRN-027 are out of scope (project owner, 2026-11-12). | TRR-033, HPV-012, HPV-013, ADM-021 |
| DEC-18 | What an "offer" is | Resolved | The offer is the trainer's course discount: percentage + start and end date, shown as price and discounted price; no separate offer entity (project owner, 2026-11-12). | TRN-010, TRN-018, ADM-013 |
| DEC-19 | Provider notification catalogue | Open | Provider receives service and booking notifications (p.87); the list is not given. | HPV-015, PLT-004 |
| DEC-20 | Center profile change approval | Resolved | Only sensitive fields (licence, IBAN) wait for admin approval; other fields save directly (project owner, 2026-11-12). | CTR-015, ADM-012 |
| DEC-21 | Package "duration" | Resolved | A start and an end date of sale on the package; the package shows its price against its courses' total (project owner, 2026-11-12). | TRR-016, ADM-013 |
| DEC-22 | Hall commission rate setting | Resolved | One global setting, copied onto each booking's commission (BR-FIN-03) (project owner, 2026-11-12). | ADM-019, ADM-051 |
| DEC-23 | Trainer package renewal vs model switching | Partly resolved | Renewal any time without carry-over (A-p.20) vs no model switch while one is active (p.128); can a commission trainer buy a package (or back) early? **Client (2026-11-12): proceed.** Build plan CRUD, subscriptions list/detail and purchase now; early renewal and model switching stay out until the rule is confirmed. | TRR-030, ADM-037 |
| DEC-24 | Several cashback rules | Resolved | Several tiers may be active; a purchase earns only the single highest tier whose required amount it reaches (on the amount actually paid, per single purchase, BR-LOY-01) (project owner, 2026-11-12; same tiered pattern as the points levels, BRD p.32). | ADM-039, TRN-019 |
| DEC-25 | Cashback pending → available | Open | Ledger has Pending / Available / Used (p.131) but the trigger is not given (payment? course completion?). | ADM-040, TRN-019 |
| DEC-26 | Level discount rate vs points conversion | Open | Levels carry a discount rate (p.32) while points convert at a fixed rate (p.133); how is the points discount computed and capped? | TRN-019, ADM-041 |
| DEC-27 | Manual notifications by the admin | Open | "Follow and send" operational notifications (p.138); can the admin broadcast manual notifications? | ADM-047, PLT-004 |
| DEC-28 | Report exports | Open | Reports have filters (p.139–140); export formats (Excel, PDF) are not specified. | ADM-048, CTR-013, ADM-024 |
| DEC-29 | Seat holding during payment | Resolved | No hold: the seat is taken when payment succeeds, re-checked under a lock so the last seat is never sold twice (project owner, 2026-11-12). | TRN-010, TRN-011 |
| DEC-30 | Notification channels | Open | In-app and email are mentioned (p.37); which events also go by push or SMS? | PLT-004 |
| DEC-31 | What buying a package creates | Resolved | All or nothing: a confirmed enrollment in every included course in one operation; refused if any course cannot take the trainee (project owner, 2026-11-12). | TRN-017, TRR-016, ADM-033 |
| DEC-32 | Delivery phasing | Open | The BRD has no delivery plan; all features are registered as phase 1 until the client splits them. | PROJECT_BRAIN §6 |
| DEC-33 | Hall commission timing (BR-HALL-14 vs BR-ADMIN-HALL-07/08) | Resolved | Pending at Accepted (not income); Due = income only when the provider confirms Booked; any withdrawal or cancellation cancels it (project owner, 2026-11-12). | ADM-019, HPV-008, HPV-010 |
| DEC-34 | Changing a course price | Resolved | The price can be changed only until the course's first confirmed enrollment; after that it is locked (the discount can still change, under review). Overrides TRR-021's price edit with enrollees (project owner, 2026-11-12). | TRR-021, ADM-028, BR-CRS-07 |

## Screen differences

Screen observations remain open until the owner confirms them; the BRD is not yet fully ingested.

| ID | Screen(s) | Difference | Outcome | Affects |
|----|-----------|------------|---------|---------|
| SCR-01 | `client--enrollment--01-trainee-checkout` | Design says points earned on enrollment; additional requirements say on course completion (pp. 10–11). | Open | Course enrollment, points |
| SCR-02 | `trainer--auth--01-academy-login`, individual registration, subscriptions, wallet | Shared academy design reference vs academy login-only and independent-only financial rules; confirm role applicability. | Open | Trainer auth, subscriptions, wallet |
| SCR-03 | `trainer--courses--02-academy-details` | Academy trainer screen offers a price action; update requires center review and approval before administration submission. | Open | Center-owned course pricing |
| SCR-04 | `client--my-courses--02-trainee-list`, `client--instructors--01-trainee-profile`, `trainer--profile--02-individual-profile` | Screens let the trainee rate the instructor (stars + comment) from a completed course and show reviews on the trainer profile; the BRD has no ratings. | Adopted (project owner, 2026-11-12): ratings are for the trainer (or the center when its course has no trainer), one per completed enrollment. | Trainee my courses, trainer profile |
| SCR-05 | `trainer--courses--03-individual-create`, `trainer--courses--04-individual-edit` | Create-course has a Sessions step (count, then a name, date and time per session); the BRD keeps only the number of sessions. | Adopted (project owner, 2026-11-12): session list stored as information only, no attendance (A-p.20). | TRR-009, TRR-021, TRN-013 |
| SCR-06 | `trainer--halls--01-individual-halls` | Booking screen uses a date range, weekdays, weeks and sessions; the BRD books manual dates/slots with no recurrence. Its summary (7 days x 20/h = 209, feature 42, total 400) also does not add up. | Open | Hall booking request (TRR-031), HPV-005 |


## Technical decisions

| ID | Topic | Status | Decision | Affects |
|----|-------|--------|----------|---------|
| TD-01 | Docs viewer, API console, docs MCP server | Accepted | `/docs`, `/tester`, `/mcp/docs` share one gate (`DocsAccess`): open on every env except `production`/`prod`; token only if `DOCS_TOKEN` is set; production needs `DOCS_ENABLED` + `DOCS_TOKEN`, never Quick Auth. | App teams, `MCP_AGENT_GUIDE.md` |
| TD-02 | Project manifest `config/docs.php` | Accepted | Project, surfaces (guard, Flutter/React, prefix, Postman folder, demo account), BRD file, ID patterns, screens folder, token budgets. Written by `project-init`; read by every docs tool. | Docs tooling |
| TD-03 | Web routes registered | Accepted | `bootstrap/app.php` loads `routes/web.php` (it was never loaded; `/` was 404). | `/docs`, `/tester` |
| TD-04 | Agent tooling | Accepted | Rules in `.kiro/steering/`; skills in `.agents/skills/` mirrored to `.claude/skills/`; `CLAUDE.md` imports `AGENTS.md` + 2 core rules; MCP: Boost (dev) + `project-docs`. | All coding agents |
| TD-05 | Token budgets | Accepted | Index files keep one short line per entry; BRD read per feature (`docs:split-brd`); features start from `docs:brief`; docs open with a Quick reference; limits in `docs.budgets`, enforced by `DocsBudgetTest`. | All agents, all docs |
| TD-06 | Reusable project base | Accepted | Project name only in `APP_NAME` (`.env` / `.env.example`); runtime names derive from it. Committed names are neutral: `project-*` skills, `project-docs` stdio handle, `project.rules`. New project = copy + `project-init` step 0. | All projects built on this base |
| TD-07 | API surfaces and consumer apps | Accepted | Five surfaces: `admin` (Vue), `client` = trainee app (Flutter), `trainer` (Flutter, independent + affiliated), `center` (Vue), `provider` = hall & event provider (Vue); each under `/api/v1/{key}`. | `config/docs.php`, routes, docs folders |
| TD-08 | Token separation between surfaces | Proposed | A token from one surface's login is refused (403) on every other surface, by account type; to be built with the first auth feature. | All surfaces, auth |
| TD-09 | Country and nationality fields | Accepted | `users.country_id` = country of residence (address) for every account type; trainer nationality is a separate field filled from Nafath (verified identity data). | Accounts, TRN-002, TRR-002 |
| TD-10 | Live course row + edit requests instead of course versions | Accepted | `courses` holds the live course; a substantive edit to a published course waits as JSON in `course_requests` (type edit) and is applied on approval (D2). Cancellation requests share the table (type cancellation, D5). | Courses, `docs/database/` |
| TD-11 | Base tables dropped or changed for Morvia | Accepted | Dropped: wallets, transactions, withdraw_requests (no money wallet; payouts outside, BR-FIN-04), governorates, regions, shipping zones, addresses (cities only, DEC-03). Slider text to translations; no category parent. | Base migrations, `docs/database/` |
| TD-12 | Bilingual notifications | Accepted | Laravel `notifications` table; `data.title` and `data.body` store Arabic and English, so the app shows the user's current language. | PLT-004, all surfaces |
| TD-13 | Domain ledgers instead of one journal | Accepted | Each money / points table is its own append-only ledger (payments, course_earnings, hall_commissions, cashback_transactions, points_transactions, enrollment refunds); balances are sums; inserts carry an idempotency key. A package price is split across its courses in proportion to their prices. | Finance, loyalty |
| TD-14 | Public uuid on every table | Accepted | Each table has `id` (foreign keys, joins) and `uuid` (CHAR(36) unique); all API routes, bodies and responses for the apps use the uuid and never expose `id`. App-generated ordered UUID. | All surfaces, models, resources |
| TD-15 | Payment gateway deferred: checkout on a contract + fake driver | Accepted | DEC-06 is open and no gateway is provided. Checkout talks only to a `PaymentGateway` contract (`payments.driver`, `fake` by default, refused in production); the fake is deterministic so purchase → payment → enrollment is fully tested now. `payments.gateway/method/gateway_reference/gateway_payload` already hold vendor data: the real driver is a later drop-in. | PLT-002, TRN-011, TRR-006 |
| TD-16 | Nafath deferred: trainer verification on a contract + fake driver | Accepted | No Nafath access yet. TRR-002 uses a `NafathGateway` contract (`nafath.driver`, `fake` by default, refused in production) and stores results in `nafath_verifications` (`provider_reference` = vendor id). The real driver is a later drop-in. | TRR-001, TRR-002, TRR-003 |
| TD-17 | Checkout assumptions (until DEC-25 and a gateway are settled) | Accepted | (1) Full course: `can_enroll` is false and checkout refuses it; a race leaving a paid payment with no seat keeps it `paid`, confirms no enrollment and flags an admin refund outside the system (D6). (2) Commission rates come from `app_configs`, copied per transaction (BR-FIN-03). (3) Cashback and points not posted yet (DEC-25 open). | TRN-011, BR-FIN-02 |
| TD-18 | Hall feature price is per slot (sprint wording "per booking date" read as per slot) | Accepted | Sprint 1 row S1-27 says a feature has a fixed price "per booking date"; BR-HALL-05, BR-HALL-07 and HPV-004/005 say once per slot, and `hall_feature_prices.price_per_slot` already stores it. Built per slot: one fixed price per feature per hall, charged once per slot of a request. Revisit only if the client confirms per-date pricing. | HPV-004, HPV-005, BR-HALL-05, BR-HALL-07 |
| TD-19 | Admin login identifier is email | Accepted | Client confirmed Sprint 1 row S1-04: admin login is email + password. ADM-001 wording ("username") is superseded for the admin surface. Center login stays username (CTR login row). | ADM-001 |
| TD-20 | Hall availability period rules | Accepted | The BRD gives date + start + end but is silent on overlap and the past. Built: one period lies within one date, periods of one hall may not overlap (touching ends allowed), a start must be in the future. Creation locks the hall row so concurrent requests cannot both pass. Revisit if the client wants overnight periods. | HPV-006 |
| TD-21 | Provider / trainer login: phone or email, matched inside the account type | Accepted | DEC-14 makes phone + password the identifier; sprint rows also say email. Both are accepted. Email and phone are unique per type only, so lookup is scoped to the surface's type (a trainee with the same phone cannot block or enter). A center-created trainer also logs in with its username. | HPV-001, TRR-003, DEC-14 |
| TD-22 | Trainer registration shape and status path | Accepted | Password is asked at step 1 (BRD lists it on the profile form) so an abandoned registration can log back in; the account exists only after the OTP. `profile_incomplete` → `under_review` added to the transitions: an independent trainer goes to review on submit, an affiliated one is active at once (TRR-004). | TRR-002, TRR-004 |
| TD-23 | Trainer-authored text is stored once for every language | Accepted | Bio, qualifications, course title and description are the trainer's own words; the API takes one string and writes it to every locale instead of requiring a translation. Revisit if the client wants separate Arabic / English copy. | TRR-002, TRR-009 |
| TD-24 | Which booking requests hold a hall slot | Accepted | BR-25 refuses a clashing slot but not which statuses count. Only `accepted` and `booked` hold a slot; a `pending` request does not, so spam cannot block a hall. The provider's accept step must re-check the clash (HPV-008). | TRR-031, BR-HALL-25 |
| TD-25 | Trainer package allowance counting and course duration | Accepted | Courses count against a package once submitted (`under_review`, `published`, `awaiting_date`, `completed`, `suspended`); draft, rejected and cancelled do not. Expiry is read from `ends_at`. A course stores date + start time + duration in minutes; the end is derived and may pass midnight. | TRR-006, TRR-009 |

---

## Resolution log

History of every decision change: [DECISIONS_LOG.md](DECISIONS_LOG.md) (newest first).
Kept out of this file so the register stays a short index — read the log only
when you need *why* or *when* something changed.
