create mvp path

This commit is contained in:
hamid
2026-08-02 20:01:31 +03:30
parent 72ab290da1
commit fb58ca54e1
203 changed files with 863 additions and 156 deletions
+19 -19
View File
@@ -15,13 +15,13 @@ step live in `docs/rules/server/` and this skill defers to them; it doesn't rest
| For | Read |
|-----|------|
| The dispatcher, folder shape, `OperationResult`, the controller skeleton, authorization | [docs/rules/server/cqrs.md](../../../docs/rules/server/cqrs.md) |
| Projects, layers, the seam catalogue, startup wiring | [docs/rules/server/structure.md](../../../docs/rules/server/structure.md) |
| EF Core, migrations, soft-delete, audit, config-as-rows, state machines, snapshots, uniqueness | [docs/rules/server/persistence.md](../../../docs/rules/server/persistence.md) |
| Anything on the money path — ledger, refunds, BNPL, payouts, invoices | [docs/rules/server/money.md](../../../docs/rules/server/money.md) |
| Auth, JWE, sessions, field encryption, tenancy | [docs/rules/server/identity.md](../../../docs/rules/server/identity.md) |
| C# style, naming, async, testing | [docs/rules/server/conventions.md](../../../docs/rules/server/conventions.md) |
| The gate, and what "done" means | [docs/rules/shared/git-and-gates.md](../../../docs/rules/shared/git-and-gates.md) |
| The dispatcher, folder shape, `OperationResult`, the controller skeleton, authorization | [docs/rules/server/cqrs.md](../../../archive/docs/rules/server/cqrs.md) |
| Projects, layers, the seam catalogue, startup wiring | [docs/rules/server/structure.md](../../../archive/docs/rules/server/structure.md) |
| EF Core, migrations, soft-delete, audit, config-as-rows, state machines, snapshots, uniqueness | [docs/rules/server/persistence.md](../../../archive/docs/rules/server/persistence.md) |
| Anything on the money path — ledger, refunds, BNPL, payouts, invoices | [docs/rules/server/money.md](../../../archive/docs/rules/server/money.md) |
| Auth, JWE, sessions, field encryption, tenancy | [docs/rules/server/identity.md](../../../archive/docs/rules/server/identity.md) |
| C# style, naming, async, testing | [docs/rules/server/conventions.md](../../../archive/docs/rules/server/conventions.md) |
| The gate, and what "done" means | [docs/rules/shared/git-and-gates.md](../../../archive/docs/rules/shared/git-and-gates.md) |
**Stack:** ASP.NET Core (.NET 10), Clean Architecture, CQRS on `martinothamar/Mediator` (a source generator —
**not MediatR**; there is no `IMediator` anywhere in this codebase), EF Core, FluentValidation, Mapster.
@@ -34,22 +34,22 @@ step live in `docs/rules/server/` and this skill defers to them; it doesn't rest
`Catalog`, `Verification`, `Search`, `Booking` (singular, pre-payment) / `Bookings` (plural, post-payment),
`Payments`, `Refunds`, `Invoices`, `Bnpl`, `Payouts`, `Reviews`, `PatientCareRecords`, `Messaging`,
`PartnerCenters`, `Configuration`, `Audit`, `Analytics`, `Holidays`, `Notifications`, `SupportAlerts`. Full
list and the schema-per-area mapping: [structure.md](../../../docs/rules/server/structure.md) §2.
list and the schema-per-area mapping: [structure.md](../../../archive/docs/rules/server/structure.md) §2.
- **Command or query, or both?** A command mutates; a query reads. Most features are a matched pair (create
+ get, or update + list).
- **Find a sibling to mirror.** Grep the area's existing folder —
`Features/<Area>/{Commands,Queries}/` — for a feature shaped like the one you're adding. Copying a live
pattern beats inventing a new one.
- **Does it touch money?** (ledger, refunds, invoices, BNPL, payouts) → read
[money.md](../../../docs/rules/server/money.md) **first**. The invariants there (integer IRR, balanced
[money.md](../../../archive/docs/rules/server/money.md) **first**. The invariants there (integer IRR, balanced
ledger postings, webhook idempotency, snapshot-at-compute-time) are not suggestions.
- **Does it add or change a table?** → read [persistence.md](../../../docs/rules/server/persistence.md) §57
- **Does it add or change a table?** → read [persistence.md](../../../archive/docs/rules/server/persistence.md) §57
before modeling it (soft-delete filters, forward-only status machines, snapshot fields, uniqueness
patterns all have a house pattern — don't reinvent one).
- **Does it need a new external dependency** (a vendor, a rail)? It becomes an interface in
`Application/Contracts/`, mock in `CrossCutting/Seams/`, real in `CrossCutting/Seams/Real/`, selected by a
`Seams:<rail>:Provider` config key that **falls closed to the mock**. See
[structure.md](../../../docs/rules/server/structure.md) §3.
[structure.md](../../../archive/docs/rules/server/structure.md) §3.
---
@@ -77,7 +77,7 @@ Baya.Application/Features/<Area>/
memory. Command: use `Include` only when you need navigation properties loaded to mutate the aggregate,
access the DB through `IUnitOfWork`, and `CommitAsync` once at the end.
Full rules and the validator/OperationResult examples: [cqrs.md](../../../docs/rules/server/cqrs.md) §13.
Full rules and the validator/OperationResult examples: [cqrs.md](../../../archive/docs/rules/server/cqrs.md) §13.
---
@@ -100,7 +100,7 @@ dotnet ef database update --project src/Infrastructure/Baya.Infrastructure.Persi
```
Full patterns, with the exact uniqueness/snapshot/state-machine tables:
[persistence.md](../../../docs/rules/server/persistence.md).
[persistence.md](../../../archive/docs/rules/server/persistence.md).
---
@@ -127,7 +127,7 @@ public sealed class MyFeatureController(ISender sender) : BaseController
`SnakeCaseParameterTransformer` will produce, rename the method instead.
- Pick the narrowest authorization that fits: none (truly public) → `[Authorize]` (any authenticated user) →
`[Authorize(ConstantPolicies.DynamicPermission)]` (role/claim-gated admin action). Table and rate-limiting
notes: [cqrs.md](../../../docs/rules/server/cqrs.md) §4.
notes: [cqrs.md](../../../archive/docs/rules/server/cqrs.md) §4.
---
@@ -140,20 +140,20 @@ public sealed class MyFeatureController(ISender sender) : BaseController
3. The recurring-job scheduler is dormant under `Testing`, so a background tick can't make an integration
test flaky — you don't need to account for it.
Examples and the full testing convention: [conventions.md](../../../docs/rules/server/conventions.md) §8.
Examples and the full testing convention: [conventions.md](../../../archive/docs/rules/server/conventions.md) §8.
---
## 6. Docs this feature triggers — in the same change
- **[`docs/integration/domains/<domain>.md`](../../../docs/integration/domains/index.md)** — add the new
- **[`docs/integration/domains/<domain>.md`](../../../archive/docs/integration/domains/index.md)** — add the new
endpoint with its verdict (`wired`/`unwired`/`phantom`), matching the client `services/` domain it belongs
to.
- **The OpenAPI snapshot** — regenerate `docs/integration/openapi/swagger.v1.json` per
[openapi/README.md](../../../docs/integration/openapi/README.md) and update its provenance table (date,
[openapi/README.md](../../../archive/docs/integration/openapi/README.md) and update its provenance table (date,
commit, path/operation counts) in the same change. A snapshot with stale provenance is what that
convention exists to prevent.
- **[`docs/status/backlog.md`](../../../docs/status/backlog.md)** — tick the row if this closes a filed
- **[`docs/status/backlog.md`](../../../archive/docs/status/backlog.md)** — tick the row if this closes a filed
item. Never delete a row; a ticked row is the record that it shipped.
- **A reference file in `docs/rules/server/`** — only if the feature introduces a genuinely new reusable
pattern, seam, or base class. Don't add prose for a feature that just follows the existing pattern.
@@ -164,4 +164,4 @@ Examples and the full testing convention: [conventions.md](../../../docs/rules/s
Run the server gate — `dotnet build Baya.sln` (**zero new warnings**) and `dotnet test Baya.sln` — and read
your diff as if reviewing the PR. Full "what done means" checklist:
[git-and-gates.md](../../../docs/rules/shared/git-and-gates.md) §2.
[git-and-gates.md](../../../archive/docs/rules/shared/git-and-gates.md) §2.
+7 -7
View File
@@ -10,14 +10,14 @@ description: >-
Exercising a flow proves something only if you know which half of the stack actually answered. This is the
procedure; the facts it points at (ports, accounts, known failure modes) live in
[docs/flows/testing-setup.md](../../../docs/flows/testing-setup.md) and are kept current there — don't copy
[docs/flows/testing-setup.md](../../../archive/docs/flows/testing-setup.md) and are kept current there — don't copy
them here, they will drift.
---
## 1. Boot it
The five-minute path, verbatim from [testing-setup.md](../../../docs/flows/testing-setup.md#the-five-minute-path):
The five-minute path, verbatim from [testing-setup.md](../../../archive/docs/flows/testing-setup.md#the-five-minute-path):
```bash
# API — mock SMS or request_otp 500s
@@ -41,7 +41,7 @@ carries a `Last verified` stamp for exactly this reason.
A flow "working" through a mocked domain proves the UI, not the server. Before testing:
1. Open [docs/integration/domains/index.md](../../../docs/integration/domains/index.md) — the census table
1. Open [docs/integration/domains/index.md](../../../archive/docs/integration/domains/index.md) — the census table
names which of the 22 client `services/` domains are real vs **mock** (currently 15 real, 7 mock:
`admin`, `bnpl`, `partnerCenter`, `patientRecords`, `payouts`, `refunds`, `verification`).
2. A mocked domain is a `USE_<DOMAIN>_MOCK` flag in `client/src/services/<domain>/constants.ts` — check it
@@ -55,7 +55,7 @@ A flow "working" through a mocked domain proves the UI, not the server. Before t
## 3. Pick the right seeded account
Demo accounts, their roles, and what each one demonstrates are tabulated in
[testing-setup.md](../../../docs/flows/testing-setup.md#demo-accounts) — read it there rather than assuming
[testing-setup.md](../../../archive/docs/flows/testing-setup.md#demo-accounts) — read it there rather than assuming
a phone number. One standing gap to route around: **the seeded admin accounts (`…020` `super_admin`,
`…021` `finance`) get 403 on every real admin endpoint** (a `DynamicPermission` / role-literal mismatch).
The admin backoffice is only testable against the client's mock; don't spend time trying to walk it against
@@ -65,7 +65,7 @@ the real API without first checking whether that gap has been closed.
## 4. Walk the flow
[docs/flows/index.md](../../../docs/flows/index.md) is the atlas — one file per user-meaningful journey,
[docs/flows/index.md](../../../archive/docs/flows/index.md) is the atlas — one file per user-meaningful journey,
each answering exactly three questions: what it does, what's mocked *for that journey specifically*, and how
to test it. Open the one file that matches what you're testing rather than guessing the steps; it's the
one place gap numbers and REQ references for that journey are tracked.
@@ -79,7 +79,7 @@ one place gap numbers and REQ references for that journey are tracked.
on a request promptly, or create a fresh one rather than trying to reuse an old test artifact.
- **The OTP endpoints are rate-limited together.** `request_otp` and `verify_otp` share one bucket, 5 calls
per 60 s per IP — a login is 2 calls, so that's **two logins per minute, total**. Space scripted logins
≥ 40 s apart (see [testing-setup.md](../../../docs/flows/testing-setup.md#scripting-logins) for a working
≥ 40 s apart (see [testing-setup.md](../../../archive/docs/flows/testing-setup.md#scripting-logins) for a working
script) or you'll 429 and misread it as a bug.
---
@@ -102,6 +102,6 @@ because the world was seeded days ago:
Name the account you used, the domain's mock/real status, and the exact response (status code, error
message) rather than "it worked" — the troubleshooting table in
[testing-setup.md](../../../docs/flows/testing-setup.md#troubleshooting) exists because several failure
[testing-setup.md](../../../archive/docs/flows/testing-setup.md#troubleshooting) exists because several failure
modes here look identical to an unrelated bug (a rate limit looks like a crash; `/healthz/ready` failing on
Windows looks like the app is down). Check it before filing something as a new defect.
+15 -15
View File
@@ -16,7 +16,7 @@ color schemes on the first try.
**Precedence.** This skill is the **design** contract — brand, tone, and the visual
decisions. The **engineering** contract is [client/CLAUDE.md](../../../client/CLAUDE.md)
(hard rules) plus [docs/rules/client/](../../../docs/rules/client/) (one reference file
(hard rules) plus [docs/rules/client/](../../../archive/docs/rules/client/) (one reference file
per area). Where the two overlap — tokens, typography, the component library, shells,
icons — **`docs/rules/client/` is authoritative and this skill defers to it.** Read the
relevant one before touching layout, provider, or data code; don't restate it here, and
@@ -24,10 +24,10 @@ never violate it.
| For | Read |
|-----|------|
| Tokens, palette, dark mode, RTL, fonts, motion | [docs/rules/client/theme.md](../../../docs/rules/client/theme.md) |
| The `App*` library, shells, navigation, icons | [docs/rules/client/components.md](../../../docs/rules/client/components.md) |
| Copy and Persian orthography | [docs/rules/client/i18n.md](../../../docs/rules/client/i18n.md) |
| Forms | [docs/rules/client/forms.md](../../../docs/rules/client/forms.md) |
| Tokens, palette, dark mode, RTL, fonts, motion | [docs/rules/client/theme.md](../../../archive/docs/rules/client/theme.md) |
| The `App*` library, shells, navigation, icons | [docs/rules/client/components.md](../../../archive/docs/rules/client/components.md) |
| Copy and Persian orthography | [docs/rules/client/i18n.md](../../../archive/docs/rules/client/i18n.md) |
| Forms | [docs/rules/client/forms.md](../../../archive/docs/rules/client/forms.md) |
**Stack:** Next.js 16 (App Router, Turbopack) · React 19 · MUI v9 (`@mui/material`) ·
Emotion (RTL via `stylis-plugin-rtl`) · next-intl v4 · notistack. Everything below
@@ -128,7 +128,7 @@ these; they're define-only in CSS):
- **Map** — `--bal-pin-shadow`, the address-picker pin.
Full catalogue, with what each group backs:
[docs/rules/client/theme.md](../../../docs/rules/client/theme.md) §2.
[docs/rules/client/theme.md](../../../archive/docs/rules/client/theme.md) §2.
---
@@ -188,7 +188,7 @@ Beyond the `App*` wrappers there is a **state kit** — `EmptyState`, `ErrorStat
`InitialsAvatar`, `FormDialogShell` — with **one pattern per state**. Never hand-roll a
dashed-border "nothing here" block or a per-screen pager; and **an error state is never an
empty state.** Catalogue in
[docs/rules/client/components.md](../../../docs/rules/client/components.md).
[docs/rules/client/components.md](../../../archive/docs/rules/client/components.md).
For layout/spacing use MUI primitives directly: `Box`, `Stack`, `Container`, `Grid`,
`Paper`, `Card`. Use the `spacing`/`sx` system (theme spacing unit = 8px) — never inline
@@ -197,18 +197,18 @@ pixel margins for rhythm.
**New shared component?** Put it in `src/components/<Name>/<Name>.tsx` with an
`index.tsx` barrel, follow the `App*` prop-spreading + JSDoc style of `AppButton.tsx`,
and add a co-located `.test.tsx` (mandatory for anything imported in >1 place — see
[docs/rules/client/testing.md](../../../docs/rules/client/testing.md); wrap with
[docs/rules/client/testing.md](../../../archive/docs/rules/client/testing.md); wrap with
`<ThemeProvider>`, never mock MUI). If it goes at the top of the `@/components/common`
barrel, prefer **caller-owned copy** (required `title`/`body`/`retryLabel` string props)
over calling `useTranslations` inside it — `next-intl` is ESM-only and poisons every test
that transitively imports the barrel. `ErrorBoundary`/`ErrorState` are the model;
[components.md](../../../docs/rules/client/components.md) has the why.
[components.md](../../../archive/docs/rules/client/components.md) has the why.
**Any form with more than one field is a react-hook-form form**, bound through the
`@/components/common/form` wrappers (`RhfTextField`, `RhfChipSelect`,
`RhfJalaliDateField`, `RhfControlGroup`) and grouped into `FormSection`s. A single-field
control is state, not a form. Full pattern:
[docs/rules/client/forms.md](../../../docs/rules/client/forms.md).
[docs/rules/client/forms.md](../../../archive/docs/rules/client/forms.md).
---
@@ -341,14 +341,14 @@ Every screen/component you produce must satisfy **all** of these:
switches automatically. Verify on both schemes — never assume a light background.
4. **Tokens, not hexes.** No raw color literals in `sx`/`styled`/components (§2).
5. **Constants, not magic values.** Cookie names, routes, repeated dimensions, event
names → named constants ([components.md](../../../docs/rules/client/components.md) §5).
names → named constants ([components.md](../../../archive/docs/rules/client/components.md) §5).
6. **Use the wrappers** (§4) and the **icon registry** (§6) before bare MUI.
7. **Shared component ⇒ co-located test** (§4).
8. **MUI v9 API only.** No v5/v6-era props (e.g. `Stack` `useFlexGap`, `storageWindow`).
Avoid deprecated APIs that throw.
9. **Persian copy follows the style guide** — «بالین‌یار» with a ZWNJ, تأیید with a hamza,
جستجو in one form, formal شما. `npm run lint:copy` fails the gate on a banned variant.
Glossary and the full rules: [i18n.md](../../../docs/rules/client/i18n.md) §4.
Glossary and the full rules: [i18n.md](../../../archive/docs/rules/client/i18n.md) §4.
10. **A screen never fabricates a figure.** A summary reads only off a query that already
answers it; a count still in flight is omitted, never faked or defaulted.
@@ -366,10 +366,10 @@ Every screen/component you produce must satisfy **all** of these:
5. **Verify the four axes:** `/fa` (RTL) and `/en` (LTR) × light and dark. The default
route is `/fa` — start there.
6. **Tests** for any new shared component; **never** add a layout above `[locale]`
(breaks locale/dir — see [structure.md](../../../docs/rules/client/structure.md)).
(breaks locale/dir — see [structure.md](../../../archive/docs/rules/client/structure.md)).
7. Data/fetch/auth/cookies/toasts → follow
[services.md](../../../docs/rules/client/services.md) and
[auth.md](../../../docs/rules/client/auth.md) (`serverFetch`/`clientFetch`,
[services.md](../../../archive/docs/rules/client/services.md) and
[auth.md](../../../archive/docs/rules/client/auth.md) (`serverFetch`/`clientFetch`,
`@/lib/cookies/*`, `dispatchToast`/`useSnackbar`). Don't reinvent these.
---
+5 -3
View File
@@ -6,9 +6,11 @@ The canonical guidance for AI coding agents in this repository lives in **[CLAUD
- Frontend → [client/CLAUDE.md](client/CLAUDE.md)
- Backend → [server/CLAUDE.md](server/CLAUDE.md)
Those hold the **hard rules**. The reasoning behind them, and everything you need on demand for a
specific area, is in **[docs/rules/](docs/rules/index.md)** — start at its index, which maps
"working on X" to the one file to open. Business rules live in **[product/](product/index.md)**.
Those hold the **hard rules**. For current-state product truth — what to test, what's blocking launch,
what's missing — start at **[mvp/README.md](mvp/README.md)**. The engineering reasoning behind the hard
rules, and the full business-requirement docs, were archived on 2026-08-02 into
**[archive/docs/rules/](archive/docs/rules/index.md)** and **[archive/product/](archive/product/index.md)**
respectively — reference material, not actively maintained.
`CLAUDE.md` is the single source of truth at every level of this repo; these `AGENTS.md` files are
just pointers so the convention is discoverable under either name.
+29 -34
View File
@@ -18,26 +18,18 @@ Balinyaar is a **trust-first home-nursing marketplace in Iran**. Independent nur
employees) list configurable services; families search, book, pay, and review. The platform holds funds in an
escrow-style ledger and pays nurses out weekly after a confirmed check-out.
Product and domain knowledge — business rules, the database model, payments/BNPL, escrow, the verification
pipeline — is **not in the code**. It lives in [`product/`](product/index.md), a structured docs tree with one
topic per file.
**Start at [`mvp/README.md`](mvp/README.md) for the current state of the product**, in three short,
non-technical files: how to manually test any user journey, what's broken and blocking a real launch, and
what's missing that isn't clearly scheduled. That folder is the live, load-bearing answer to "what's next."
| Folder | What it covers |
| --- | --- |
| [product/overview/](product/overview/platform-summary.md) | What Balinyaar is, the four cross-cutting ground truths, the Persian glossary. **Read first.** |
| [product/business/](product/business/index.md) | The 14 functional/business requirement areas, one file each |
| [product/data-model/](product/data-model/index.md) | The ~54-table SQL Server schema across 13 domains, + [diagrams](product/data-model/diagrams.md) |
| [product/payments/](product/payments/index.md) | BNPL, the escrow ledger, settlement, VAT, integrations (with sources) |
| [product/research/](product/research/index.md) | Market/legal/verification research & go-to-market (EN) |
| [product/notes/](product/notes/open-questions.md) | Living notes: open questions, future ideas |
| [product/fa/](product/fa/index.html) | Farsi versions (research report + verification flow) |
Deeper product/business knowledge — the full business-requirement write-ups, the ~54-table database model,
payments/BNPL research, market/legal research — was consolidated into [`archive/product/`](archive/product/index.md)
during the 2026-08-02 documentation cleanup. It is **reference material, not required reading**: correct as
of that date, but not actively maintained going forward. Read it when `mvp/` doesn't answer your question in
enough depth — e.g. designing a new table, or needing the full reasoning behind a business rule.
**Read the relevant `product/` doc before designing any schema, API, or feature.** Don't infer business rules
from code — the code is young and the docs are the source of truth.
> **Docs format:** the `.md` files are canonical; matching `.html` files are a generated, cross-linked browsing
> view (`cd product && node build-docs.mjs`). Edit the Markdown and regenerate — never hand-edit the `.html`.
> If you add or rename a `.md`, update the `NAV` manifest in `product/build-docs.mjs`.
**Never infer business rules from code alone** — the code is young. If `mvp/` and `archive/product/` both go
silent on a money, auth, tenancy, or clinical-data rule, say so rather than guessing.
---
@@ -50,9 +42,8 @@ package, or solution — each project is built, linted, and run on its own.
| --- | --- | --- | --- |
| [`client/`](client/) | Web frontend | Next.js 16 (App Router) · React 19 · TypeScript · MUI v9 · next-intl | [client/CLAUDE.md](client/CLAUDE.md) |
| [`server/`](server/) | Backend API | ASP.NET Core (.NET 10) · Clean Architecture · CQRS · EF Core | [server/CLAUDE.md](server/CLAUDE.md) |
| [`product/`](product/index.md) | **Business truth**what to build and why | Markdown (+ generated HTML) | the table above |
| [`docs/`](docs/README.md) | **Engineering truth** — rules, the client↔server contract, flows, status, roadmap | Markdown | [docs/README.md](docs/README.md) |
| [`archive/`](archive/README.md) | The executed build-chain (was `dev/`) and the cleanup plan that produced `docs/`. **History, not instruction** — nothing to build from it | Markdown | [archive/README.md](archive/README.md) |
| [`mvp/`](mvp/README.md) | **Current truth**plain-language test flows, launch blockers, missing MVP features | Markdown | [mvp/README.md](mvp/README.md) |
| [`archive/`](archive/README.md) | Everything else: business docs, engineering rules/contracts/flow-atlas, and the executed build history. **Reference/history, not instruction** — nothing to build from it, and nothing here is kept current | Markdown | [archive/README.md](archive/README.md) |
| [`telegram-otp-bot/`](telegram-otp-bot/) | OTP relay (standalone, the pre-launch demo rail) | Node 18+, zero deps | [telegram-otp-bot/README.md](telegram-otp-bot/README.md) |
| [`deploy/`](deploy/) | Reverse-proxy config | Caddyfile | [DEPLOY.md](DEPLOY.md) |
@@ -67,8 +58,10 @@ The two projects communicate over **HTTP/JSON** (optionally gRPC). The client re
network, serving `balinyaar.ir` (client) and `api.balinyaar.ir` (server). The database is **not**
containerised; it is a remote SQL Server. Full runbook: [DEPLOY.md](DEPLOY.md).
`archive/` holds `dev/`'s history now that the clarify chain has run. **Anything in it is a record, not
an instruction** — it is written in the imperative from having once been a prompt.
`archive/` holds the executed build history, the former `docs/` (engineering rules, API contracts, the
per-flow test atlas, status/backlog) and the former `product/` (business requirements, data model, research)
— consolidated there on 2026-08-02 so the live tree stays focused on MVP work. **Anything in it is a record,
not an instruction.**
---
@@ -80,14 +73,15 @@ are touching.
| Tier | Where | What |
| --- | --- | --- |
| **Hard rules** | this file · [client/CLAUDE.md](client/CLAUDE.md) · [server/CLAUDE.md](server/CLAUDE.md) | Constraints whose violation breaks the build, the gate, or a business invariant |
| **Reference** | [`docs/rules/`](docs/rules/index.md) | The *how* and the *why*, read on demand — 3 shared files, 8 client, 6 server, plus the documentation convention |
| **Reference** (archived) | [`archive/docs/rules/`](archive/docs/rules/index.md) | The *how* and the *why*, as of 2026-08-02 — 3 shared files, 8 client, 6 server, plus the documentation convention. Not actively maintained; read it on demand, don't expect it to track later changes |
| **Procedure** | `.claude/skills/` | Playbooks: **frontend-designer** (the design contract for `client/` UI), **backend-feature** (adding a server feature), **flow-testing** (walking a flow end to end) |
Start at [docs/rules/index.md](docs/rules/index.md) — it maps "working on X" to the one file to open.
Start at [archive/docs/rules/index.md](archive/docs/rules/index.md) — it maps "working on X" to the one file
to open.
**Precedence when two sources disagree:** `product/` (business truth) → the relevant `CLAUDE.md` (engineering
truth) → `docs/rules/` (the reasoning behind it) → the task in front of you. **Never silently guess on money,
auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
**Precedence when two sources disagree:** `archive/product/` (business truth) → the relevant `CLAUDE.md`
(engineering truth) → `archive/docs/rules/` (the reasoning behind it) → the task in front of you. **Never
silently guess on money, auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
---
@@ -100,8 +94,8 @@ auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
- client: `cd client && npm run check` (type + lint + copy), plus `npm run test:ci` if you touched a tested
component.
- server: `cd server && dotnet build Baya.sln` (**zero new warnings**) and `dotnet test Baya.sln`.
- What "done" means in full: [docs/rules/shared/git-and-gates.md](docs/rules/shared/git-and-gates.md).
4. **Read the product docs before changing behavior.** Business rules are decisions, not guesses.
- What "done" means in full: [archive/docs/rules/shared/git-and-gates.md](archive/docs/rules/shared/git-and-gates.md).
4. **Read [`mvp/`](mvp/README.md) (and `archive/product/` for depth) before changing behavior.** Business rules are decisions, not guesses.
5. **Don't reintroduce template/starter scaffolding.** Both projects were derived from open-source starters;
their branding, demo/showcase pages, and `_TITLE_`/`_DESCRIPTION_` placeholders were intentionally removed.
Don't add them back.
@@ -121,7 +115,7 @@ auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
renames a project, layer, route group, provider, or major folder, or changes a cross-project / cross-layer
boundary — update the matching section in the same change. The full anti-drift convention (what to update
when X changes, the `> Last verified:` stamp, length budgets) is
[docs/rules/documentation.md](docs/rules/documentation.md). **Stale instructions are worse than none.**
[archive/docs/rules/documentation.md](archive/docs/rules/documentation.md). **Stale instructions are worse than none.**
8. **Write clean, self-documenting code.**
- **No dead code.** Remove unused variables, imports/usings, parameters, and private members — don't leave
them behind and don't suppress the warning. The client enforces this with ESLint
@@ -130,9 +124,10 @@ auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
- **Comment the *why*, not the *what*.** Don't write verbose comments that restate what the code already
says. Add a comment only where a non-obvious decision, constraint, business rule, or trade-off isn't
evident from the code itself. Prefer a clearer name over a comment.
- Details and worked examples: [docs/rules/shared/code-quality.md](docs/rules/shared/code-quality.md).
- Details and worked examples: [archive/docs/rules/shared/code-quality.md](archive/docs/rules/shared/code-quality.md).
9. **A mock is only sanctioned behind a DI-registered seam**, selected by configuration, defaulting to the
mock, and recorded in `docs/status/`. Never an `if (mock)` branch scattered through the code.
mock, and recorded in [`mvp/blockers.md`](mvp/blockers.md) (or `archive/docs/status/` for the full historical
ledger). Never an `if (mock)` branch scattered through the code.
---
@@ -144,7 +139,7 @@ auth, tenancy, or clinical-data rules** — do the safe thing, and say so.
The product/brand name is **Balinyaar** — «بالین‌یار» in Persian copy, with a ZWNJ, always. The server's
`Baya*` prefix is a legacy code namespace: **do not rename it without explicit instruction.** Full
conventions: [docs/rules/shared/naming.md](docs/rules/shared/naming.md).
conventions: [archive/docs/rules/shared/naming.md](archive/docs/rules/shared/naming.md).
---
+6 -5
View File
@@ -4,10 +4,11 @@ A first, shareable deployment of the whole stack under **balinyaar.ir**, in Dock
Caddy reverse proxy that terminates TLS.
> **This file is the deploy *procedure*.** The runtime dependency graph — every edge, what breaks when it is
> down, and where it is configured — is [docs/integration/topology.md](docs/integration/topology.md), and
> down, and where it is configured — is [archive/docs/integration/topology.md](archive/docs/integration/topology.md)
> (archived reference, not actively maintained), and
> every configuration key on both sides is
> [docs/integration/config-matrix.md](docs/integration/config-matrix.md). Read those to answer "what talks
> to what" or "where is this value set"; read this one to actually ship.
> [archive/docs/integration/config-matrix.md](archive/docs/integration/config-matrix.md). Read those to answer
> "what talks to what" or "where is this value set"; read this one to actually ship.
| Host | Serves | Container |
| --- | --- | --- |
@@ -37,8 +38,8 @@ machine is now inert and can be deleted. Every value lives in a file in the repo
The placeholder string `SET_VIA_USER_SECRETS_OR_ENV` in the base `appsettings.json` names that removed
store; the *name* is a historical artifact, kept only because it is the sentinel `StartupSecretsGuard`
rejects. **The mechanism is appsettings files and environment variables** — see
[docs/integration/config-matrix.md](docs/integration/config-matrix.md), which lists every key, its default,
and who reads it.
[archive/docs/integration/config-matrix.md](archive/docs/integration/config-matrix.md), which lists every key,
its default, and who reads it.
The API runs as **`ASPNETCORE_ENVIRONMENT=Development`**, so `appsettings.Development.json` is the file
that actually loads. There is **no `appsettings.Production.json` in the repo at all**, and adding one would
+36 -18
View File
@@ -1,13 +1,22 @@
# Archive
> **This folder is a historical record of how Balinyaar was built. It is not instruction.**
> Nothing here describes current behaviour, current rules, or current plans. Do not follow a
> procedure from this folder. Current truth lives in [`docs/`](../docs/README.md) and
> [`product/`](../product/index.md).
> **This folder is a historical and reference record. It is not instruction.**
> Nothing here describes current priorities or the current plan. Do not follow a procedure from this
> folder. The current, load-bearing answers to "what do I test" / "what's broken" / "what's missing
> for MVP" live in **[`mvp/`](../mvp/README.md)** — read that first.
Everything here was written in the imperative, as a prompt for an agent to execute. The work described
was executed weeks ago; the code has moved on since. Reading a file in this tree as if it were a
live instruction is the exact failure mode this archive exists to prevent.
As of 2026-08-02, this folder absorbed **all** of the project's accumulated documentation — not just the
executed build-chain history, but also the full `docs/` (engineering rules, integration contracts, flow
atlas, status/backlog) and `product/` (business requirements, data model, payments research) trees that
used to live at the repo root. That reorganization was a deliberate cleanup: those trees had grown large
enough to slow down MVP-focused work, and their two truly current-state questions — "how do I test this"
and "what's blocking/missing for MVP" — were distilled forward into `mvp/`. Everything else here is kept
as raw material for a future, more thorough compaction pass; nothing in `mvp/` links back into this folder.
Everything in the pre-existing subfolders below was additionally written in the imperative, as a prompt for
an agent to execute. The work described was executed weeks to months ago; the code has moved on since.
Reading a file in this tree as if it were a live instruction is the exact failure mode this archive exists
to prevent.
---
@@ -15,12 +24,14 @@ live instruction is the exact failure mode this archive exists to prevent.
| Folder | Was | Date range | Superseded by |
| --- | --- | --- | --- |
| `build-chain/phases/` | `dev/phases/` — 32 executed build prompts (backend 015, frontend 015) plus `_shared/` conventions | 2026-06-28 (single day, all executed) | [`docs/rules/`](../docs/rules/index.md) (conventions), [`docs/flows/`](../docs/flows/index.md) (§7 "How to test" sections), [`docs/status/decisions.md`](../docs/status/decisions.md) (§5 "Critical rules") |
| `build-chain/working-context/` | `dev/shared-working-context/` — per-phase STATUS files, 50 handoff/report files, the frontend request ledger, the mocks registry | 2026-06-28 → 2026-07-20 | [`docs/status/decisions.md`](../docs/status/decisions.md), [`docs/status/implemented.md`](../docs/status/implemented.md), [`docs/status/backlog.md`](../docs/status/backlog.md) (67 REQs → `BL-###`) |
| `build-chain/contracts/` | `dev/contracts/` — the original hand-written API contract layer + the frozen 2026-07-13 OpenAPI snapshot | 2026-06-28 → 2026-07-13 | [`docs/integration/`](../docs/integration/index.md) (refreshed against 2026-07-29 code, domain-by-domain) |
| `post-phase/` | `dev/post-phase/` — hardening (18 items), refinement (10 phases), server follow-up plans, and the 15-phase UI overhaul (plans + design audits) | 2026-07-10 → 2026-07-28 | [`docs/status/backlog.md`](../docs/status/backlog.md) (hardening + server items, re-verified against code, not trusted from checkboxes), [`docs/status/decisions.md`](../docs/status/decisions.md) (refinement decisions), [`docs/flows/testing-setup.md`](../docs/flows/testing-setup.md) (RUNBOOK.md, manual-testing-plan.md), the `frontend-designer` skill (UI design reality) |
| `manual-testing/` | `dev/manual-testing/` — two iterations of human testing notes + screenshots (the only visual record of the pre-overhaul UI) | 2026-07-27 | [`docs/status/backlog.md`](../docs/status/backlog.md) (unfinished items); screenshots are kept as-is, unlinked from any live doc |
| `clarify-chain/` | `docs/_plan/` — the plan that produced this cleanup: inventory, contradiction log, and the eight phase files (including this move) | 2026-07-29 → 2026-08-02 | [`docs/README.md`](../docs/README.md) records when it ran; its content is itself now history |
| `build-chain/phases/` | `dev/phases/` — 32 executed build prompts (backend 015, frontend 015) plus `_shared/` conventions | 2026-06-28 (single day, all executed) | `docs/rules/` (conventions), `docs/flows/` (§7 "How to test" sections), `docs/status/decisions.md` (§5 "Critical rules") — all now archived alongside this folder, see below |
| `build-chain/working-context/` | `dev/shared-working-context/` — per-phase STATUS files, 50 handoff/report files, the frontend request ledger, the mocks registry | 2026-06-28 → 2026-07-20 | `docs/status/decisions.md`, `docs/status/implemented.md`, `docs/status/backlog.md` (67 REQs → `BL-###`) |
| `build-chain/contracts/` | `dev/contracts/` — the original hand-written API contract layer + the frozen 2026-07-13 OpenAPI snapshot | 2026-06-28 → 2026-07-13 | `docs/integration/` (refreshed against 2026-07-29 code, domain-by-domain) |
| `post-phase/` | `dev/post-phase/` — hardening (18 items), refinement (10 phases), server follow-up plans, and the 15-phase UI overhaul (plans + design audits) | 2026-07-10 → 2026-07-28 | `docs/status/backlog.md` (hardening + server items, re-verified against code, not trusted from checkboxes), `docs/status/decisions.md` (refinement decisions), `docs/flows/testing-setup.md` (RUNBOOK.md, manual-testing-plan.md), the `frontend-designer` skill (UI design reality) |
| `manual-testing/` | `dev/manual-testing/` — two iterations of human testing notes + screenshots (the only visual record of the pre-overhaul UI) | 2026-07-27 | `docs/status/backlog.md` (unfinished items); screenshots are kept as-is, unlinked from any live doc |
| `clarify-chain/` | `docs/_plan/` — the plan that produced the first documentation clean-up pass (the one that built `docs/` and `docs/status/backlog.md` out of the rows above) | 2026-07-29 → 2026-08-02 | superseded in turn by the 2026-08-02 consolidation into `mvp/` described at the top of this file |
| `docs/` | The engineering-truth tree produced by `clarify-chain/` — rules, integration contracts, the 23-flow test atlas, status/backlog/roadmap | 2026-07-29 → 2026-08-02 | `mvp/test-flows.md` (flow atlas, distilled) and `mvp/blockers.md` (backlog/roadmap, distilled) |
| `product/` | Business truth — the 14 business-requirement areas, the data model, payments research, market/legal research | pre-existing, never previously archived | `mvp/blockers.md` and `mvp/forgotten-features.md` pull the launch-critical and scope-decision facts forward; the rest (schema detail, market research) has no live equivalent — read it here if you need it |
`dev/README.md`'s own context (why this history exists at all — the derivation from an open-source
starter, the phase-chain-then-post-phase-then-UI-overhaul shape) is folded into this file rather than
@@ -34,11 +45,18 @@ here because they sit in files a reader might otherwise trust:
- `post-phase/manual-testing-plan.md` and some of `post-phase/refinement/RUNBOOK.md` still instruct
`dotnet user-secrets` — removed from the codebase in `5885280`. Config lives in `appsettings.*.json`
and `.env.*` files; see [`docs/README.md`](../docs/README.md#configuration).
and `.env.*` files; see `docs/README.md#configuration` in this same archive.
- `post-phase/hardening/issues.md` shows 18 of 18 items unticked as of 2026-07-17, but four later
work chains ran without updating it. The real state is in
[`docs/status/backlog.md`](../docs/status/backlog.md), re-verified against code.
work chains ran without updating it. The real state, as of the 2026-08-02 consolidation, is
distilled in [`../mvp/blockers.md`](../mvp/blockers.md).
## `product/` is untouched
## `docs/` and `product/` — how they got here
Nothing under `product/` moved. It was, and remains, business truth, not build history.
Both were live, current-truth trees at the repo root until 2026-08-02. Neither was wrong or out of date —
they were simply large enough (83 and 48 files respectively, plus this folder's pre-existing ~220) that
finding "what do I test" or "what's blocking MVP" meant reading through a great deal of settled history and
reference material first. [`../mvp/`](../mvp/README.md) now carries those two live questions forward in
three short files; everything else that made `docs/` and `product/` valuable — the full business-requirement
write-ups, the ~54-table data model, the per-domain API contracts, the payments/legal research, the
per-flow technical trace with file:line evidence — is preserved here, unedited, for whoever does the next,
more thorough compaction pass.

Some files were not shown because too many files have changed in this diff Show More