Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ do not create a commit until every required check passes.
```bash
npm run typecheck
npm run lint
npm run server:test
npm run build
npm run knip
```
Expand Down
1 change: 1 addition & 0 deletions .agents/rules/git.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Use this guidance only when the user asks to commit, inspect history, or prepare
npm run format:check
npm run test:coverage
npm run test:contract
npm run server:test
npm run knip
npm run performance
npm run build-storybook
Expand Down
3 changes: 2 additions & 1 deletion .agents/rules/react.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ All user-visible text should go through `react-i18next`.
## Routing

- Define route keys and paths in `src/app/config/routes.ts`.
- Update `src/app/hooks/useAllowedRoutes.ts` when route access changes.
- Update `src/app/config/routes.ts` when route access changes. Keep access
decisions in the pure policy functions under `src/app/lib`.
1 change: 1 addition & 0 deletions .agents/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"npm run format:check",
"npm run test:coverage",
"npm run test:contract",
"npm run server:test",
"npm run knip",
"npm run build",
"npm run performance",
Expand Down
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
VITE_API_BASE_URL=https://localhost:8080
MOCK_ALLOWED_ORIGIN=http://127.0.0.1:5173
VITE_API_BASE_URL=http://127.0.0.1:3000
VITE_APP_BASE_URL=/
VITE_OBSERVABILITY_URL=https://observability.example.com/events
VITE_RELEASE_ID=local
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ jobs:

- run: npm run test:contract

- run: npm run server:test

- if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ npm run lint
npm run format:check
npm run test:coverage
npm run test:contract
npm run server:test
npm run knip
npm run performance
npm run build-storybook
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ npm run dev
npm run dev # start Vite dev server
npm run build # typecheck and build for production
npm run preview # preview production build
npm run server # start the collection-driven local mock API
npm run server:test # test the local mock API
npm run lint # run ESLint
npm run lint:fix # run ESLint with auto-fix
npm run audit # check dependencies for high-severity vulnerabilities
Expand All @@ -62,6 +64,10 @@ npm run knip # detect unused files, exports, and dependencies

Example values are available in `.env.example`.

For local development without a backend, start `npm run server`, set
`VITE_API_BASE_URL=http://127.0.0.1:3000`, and sign in with `09123456789` /
`password123`. See the [mock server guide](server/README.md).

## Routes

| Path | Page | Access |
Expand All @@ -71,7 +77,7 @@ Example values are available in `.env.example`.
| `/auth/register` | Registration | public |
| `/` | Empty dashboard starter page | authenticated |
| `/account` | Profile, username, email, and password | authenticated |
| `/roles` | Roles and permissions | `role_read` |
| `/roles` | Roles and permissions | `roles.read` |
| `/users` | Users | `users.read` |
| `*` | Not found | public fallback |

Expand Down Expand Up @@ -103,7 +109,7 @@ Permission contracts live in `src/features/roles/types.ts`; route and action
permission mappings live in `src/app/config/routes.ts`. Every route declares
its public, authenticated, or permission-gated `permissions.access` rule.
Permission-gated routes use `.read` permissions for access and can expose
create, delete, and update actions through `useRoutePermissions`:
create, delete, and update actions through `getRoutePermissions(route, user)`:

```ts
// Route access
Expand All @@ -120,7 +126,7 @@ Password pages/actions only require a valid auth token.

```text
src/
app/ Application composition, routes, providers, contexts, and app hooks
app/ Application composition, routes, providers, access policy, and app hooks
assets/ Fonts and global styles
features/ Account, authentication, role, user, and dashboard slices
layouts/ Auth and authenticated application shells
Expand Down
10 changes: 10 additions & 0 deletions collection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,13 @@ Saved response files sit beside each request and are named after their HTTP
status code.

Do not store real passwords or access tokens in this shared collection.

## Local mock integration

The development mock server reads this directory directly at startup. Run it
from the repository root with `npm run server`; changes to requests or saved
responses take effect after restarting the process. Run `npm run server:test`
after contract changes.

See the [collection and mock integration guide](../docs/collection-guide.md) for
source-of-truth rules, change sequencing, error simulation, and limitations.
49 changes: 33 additions & 16 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,39 @@ This page maps every maintained project area to its source of truth. A change
that introduces a new subsystem, workflow, environment variable, or public
contract must add or update an entry here.

| Area | Primary documentation | Implementation and configuration |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Setup, scripts, and local development | [Development](development.md) | `package.json`, `.nvmrc`, `.env.example`, Vite and TypeScript configs |
| Application structure and boundaries | [Architecture](architecture.md) | `src/app`, `src/features`, `src/layouts`, `src/shared`, `eslint.config.ts` |
| Routes, permissions, localization, theme, fonts, and storage | [Architecture](architecture.md) | `src/app`, `src/shared/config`, `src/shared/i18n`, `src/shared/storage`, `src/assets` |
| HTTP, authentication, token refresh, and endpoint contracts | [API client](api-client.md) | `src/shared/api`, feature `api.ts` and `types.ts` files |
| Unit, component, integration, browser, accessibility, visual, and Storybook testing | [Testing](testing.md) | Vitest, Playwright, `.storybook`, `e2e`, and `src/test` |
| Consumer contracts and mutation testing | [Mutation and contract testing](contract-testing.md) | `contract`, `vitest.contract.config.ts`, `stryker.config.json` |
| Build, environment validation, nginx, security headers, observability, and performance | [Deployment](deployment.md) | `vite.config.ts`, `nginx.conf`, `scripts`, `smoke` |
| Staging validation | [Staging](staging.md) | `staging`, `staging.config.ts`, staging workflow |
| CI checks and merge policy | [Branch protection](branch-protection.md) | CI and CodeQL workflows, `CODEOWNERS`, GitHub branch settings |
| Versioning and release automation | [Versioning and releases](releasing.md) | Release workflow, Release Please config, changelog and manifest |
| Production approval, promotion, rollback, and incident follow-up template | [Release operations](release-operations.md) | Deployment-smoke workflow and downstream environment controls |
| Static analysis | [SonarQube](sonarqube.md) | `sonar-project.properties` and advisory CI scan |
| Security policy and assurance | [Security policy](../SECURITY.md) and `security/` reviews | CodeQL and authorized DAST workflows, threat model |
| AI assistant rules and safety hooks | [AI guidance](../.agents/README.md) | `AGENTS.md`, `.agents/settings.json`, `.agents/rules`, `.agents/hooks` |
## Evidence and source-of-truth rules

Documentation explains the system but does not override executable contracts or
implementation. When sources disagree:

1. The Bruno collection defines observable HTTP behavior.
2. TypeScript types and feature API modules define the frontend integration boundary.
3. Runtime code defines current UI behavior and state ownership.
4. Narrative documents summarize those sources and must change with them.

Do not present planned behavior as implemented. Update the collection before
changing an observable external contract.

| Area | Primary documentation | Implementation and configuration |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| Setup, scripts, and local development | [Development](development.md) | `package.json`, `.nvmrc`, `.env.example`, Vite and TypeScript configs |
| Executable HTTP collection and frontend integration | [Collection guide](collection-guide.md) | `collection`, feature API/types modules, contract tests |
| Local collection-driven mock API | [Mock server guide](../server/README.md) and [Collection guide](collection-guide.md) | `server`, `collection`, root `server:*` scripts |
| Application structure and boundaries | [Architecture](architecture.md) | `src/app`, `src/features`, `src/layouts`, `src/shared`, `eslint.config.ts` |
| Routes, permissions, localization, theme, fonts, and storage | [Architecture](architecture.md) | `src/app`, `src/shared/config`, `src/shared/i18n`, `src/shared/storage`, `src/assets` |
| Production-file test and Storybook expectations | [Component coverage](component-coverage.md) | `src`, unit and integration tests, stories, Storybook |
| Implemented compatibility, coverage, accessibility, security, and performance gates | [Quality attributes](quality-attributes.md) | Engines, Vitest, CI, Playwright, Lighthouse, security and bundle configuration |
| HTTP, authentication, token refresh, and endpoint contracts | [API client](api-client.md) | `src/shared/api`, feature `api.ts` and `types.ts` files |
| Unit, component, integration, browser, accessibility, visual, and Storybook testing | [Testing](testing.md) | Vitest, Playwright, `.storybook`, `e2e`, and `src/test` |
| Consumer contracts and mutation testing | [Mutation and contract testing](contract-testing.md) | `contract`, `vitest.contract.config.ts`, `stryker.config.json` |
| Build, environment validation, nginx, security headers, observability, and performance | [Deployment](deployment.md) | `vite.config.ts`, `nginx.conf`, `scripts`, `smoke` |
| Staging validation | [Staging](staging.md) | `staging`, `staging.config.ts`, staging workflow |
| CI checks and merge policy | [Branch protection](branch-protection.md) | CI and CodeQL workflows, `CODEOWNERS`, GitHub branch settings |
| Versioning and release automation | [Versioning and releases](releasing.md) | Release workflow, Release Please config, changelog and manifest |
| Production approval, promotion, rollback, and incident follow-up template | [Release operations](release-operations.md) | Deployment-smoke workflow and downstream environment controls |
| Static analysis | [SonarQube](sonarqube.md) | `sonar-project.properties` and advisory CI scan |
| Security policy and assurance | [Security policy](../SECURITY.md) and `security/` reviews | CodeQL and authorized DAST workflows, threat model |
| AI assistant rules and safety hooks | [AI guidance](../.agents/README.md) | `AGENTS.md`, `.agents/settings.json`, `.agents/rules`, `.agents/hooks` |

Generated output directories such as `dist`, `coverage`, `pacts`, Storybook,
Lighthouse, mutation, and Playwright reports are intentionally excluded from
Expand Down
11 changes: 10 additions & 1 deletion docs/api-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The API layer uses `src/shared/api/client.ts` as a small Axios wrapper around th
- Automatic snake_case request body conversion
- Manual snake_case query parameter conversion where endpoints pass `params`
- Configurable unauthorized handler for `401` responses
- Typed helpers for JSON and blob responses
- Typed helpers for JSON, `FormData`, and blob responses

## Client Helpers

Expand All @@ -25,6 +25,10 @@ apiClient.del<T>(url, config);
apiClient.blob(url, config);
```

`post` and `put` accept either plain request objects or `FormData`. Wire-case
conversion applies recursively to plain objects; browser-native `FormData`
instances pass through unchanged.

## Starter Modules

| File | Purpose |
Expand Down Expand Up @@ -70,3 +74,8 @@ apiClient.blob(url, config);
## Adding Modules

Add endpoint helpers to the owning feature's `api.ts`. Put only transport-level code used by multiple features in `src/shared/api`; do not create a global domain-service barrel.

Update the corresponding Bruno operation and saved response before changing an
observable endpoint contract. The local mock reloads those contracts on process
restart; see the [collection guide](collection-guide.md) and
[mock server guide](../server/README.md).
26 changes: 19 additions & 7 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ It also synchronizes language and theme with local storage and configures Day.js

### Ant Design Provider

`AntdProvider` configures Ant Design for the current language and theme. It is the place to change global component tokens or locale behavior.
`AntdProvider` configures Ant Design for the current language and theme and
mounts Ant Design's application boundary. Components obtain message, modal,
notification, and token APIs through `useAntd`, which delegates to
`AntdApp.useApp` rather than a project-owned context.

## Routing

Expand All @@ -42,13 +45,14 @@ The app uses two layouts:
- `AuthLayout` for `/auth`
- `DefaultLayout` for authenticated application pages

`SetCurrentRoute` wraps each route element and updates `CoreProvider` with the active route key. Navigation components should prefer `routeTree` rather than hard-coded paths.
`RouteWrapper` wraps each route element and updates `CoreProvider` with the active route key. Navigation components should prefer `routeTree` rather than hard-coded paths. The root router error boundary reports route and layout failures through observability and renders the shared application fallback.

`useAllowedRoutes` derives visible and accessible routes from each entry's
`permissions.access` value. Features use `useRoutePermissions(route)` to derive
named action booleans such as `canCreate` and `canUpdate` from the same entry.
`useAllowedNavigation` filters `navigationTree` recursively, so empty menu
groups are omitted and nested groups are supported.
Pure policy functions in `src/app/lib/access.ts` evaluate route access, derive
named action booleans such as `canCreate` and `canUpdate`, and filter
`navigationTree` recursively. Router, layout, and feature components pass the
current account to these functions directly; access policy does not depend on
React hooks. Empty navigation groups are omitted and nested groups are
supported.
`public` routes are always reachable, `authenticated` routes require a signed-in
user, and permission-gated routes require the declared permission unless the
user is a system administrator. These browser checks improve the user
Expand Down Expand Up @@ -101,3 +105,11 @@ variable WOFF2 from `src/assets/fonts/vazirmatn` and uses weights 100–900 with
builds; the application does not depend on an external font provider.

Prefer Ant Design components and theme tokens for new UI so layout, spacing, RTL behavior, and dark/light themes stay consistent.

## Local API Boundary

The Bruno collection defines the executable HTTP boundary. Feature API modules
and types consume it, Pact tests protect selected consumer contracts, and the
dependency-free server under `server/` reads it directly for local development.
The mock server is a development adapter, not part of the browser application or
production deployment architecture. See the [collection guide](collection-guide.md).
Loading
Loading