Streamline agent instructions

This commit is contained in:
2026-04-29 17:00:23 +03:00
parent 4d35fa3da0
commit 58e4202e99
+83 -142
View File
@@ -1,182 +1,123 @@
# AGENTS.md Aeroflot.Flights.Web
# AGENTS.md - Aeroflot.Flights.Web
## Quick Start
## Read First
React 18 SSR app on Modern.js 2.70.8 with Rspack and Module Federation 2.3.3. It is deployed both as a standalone SSR app and as a remote frontend component for customer Web/PWA hosts.
Work in `src/`. Treat `ClientApp/` as legacy Angular 12 reference only unless the user explicitly asks otherwise.
Prefer small, local changes that match the existing architecture. Do not widen dependencies across layers, and do not introduce browser-only imports into SSR paths.
## Commands
```bash
# Install dependencies
pnpm install
# Development servers
pnpm dev # Modern.js on :8081
pnpm dev:full # Proxy on :8080 (API forwarding via curl to bypass WAF)
pnpm dev:full # Proxy on :8080; forwards API via curl
# Build targets
pnpm build:standalone # SSR server at dist/standalone/
pnpm build:remote # MF remote at dist/remote/ (with mf-manifest.json)
pnpm build:both # Both targets
# Quality checks (run in order)
pnpm typecheck
pnpm lint
pnpm test
pnpm test:coverage
pnpm bundle-size # CI gate: total gzip ≤ 2000 kB
pnpm check-coverage # CI gate: line coverage 65%
pnpm bundle-size # remote gzip budget: <= 2000 kB
pnpm check-coverage # line coverage gate: >= 65%
# E2E tests
pnpm test:e2e # React app (port 8080)
pnpm test:e2e:angular # Angular app (port 4203)
pnpm build:standalone # dist/standalone/
pnpm build:remote # dist/remote/ with mf-manifest.json
pnpm build:both
pnpm test:e2e # React app, baseURL http://localhost:8080
pnpm test:e2e:angular # Legacy Angular app, port 4203
```
## Current State
## Critical Rules
React 18 SSR application built with **Modern.js 2.70.8** (Rspack bundler) and **Module Federation 2.3.3**. The app is a remote frontend component embeddable in the customer's channel apps (Web, PWA).
**Stack:** Modern.js 2.70.8, React 18.2, Rspack, Module Federation 2.3.3, i18next (9 languages), PrimeReact, Leaflet, SignalR, OpenTelemetry, Vitest, Playwright.
**Source:** `src/` (file-based routing under `src/routes/`). Legacy Angular 12 SPA in `ClientApp/` (read-only reference, not deployed).
**Builds:** `pnpm build:standalone` (SSR server at `dist/standalone/`), `pnpm build:remote` (MF remote at `dist/remote/` with `mf-manifest.json`).
**Dev:** `pnpm dev` (Modern.js on :8081), `pnpm dev:full` (proxy on :8080 with API forwarding via curl to bypass WAF).
**Known constraint:** Modern.js 3.x upgrade is blocked by `@module-federation/modern-js` ESM incompatibilities (broken `__filename`/`require` in ESM bundles, missing `api.modifyWebpackConfig` in Rsbuild 2.0). React Router v7 future flags are enabled to suppress deprecation warnings.
## Contractual Requirements
The following are contractual hard constraints for the remote frontend component.
### 1. Tech Stack
- **ModernJS (SSR)** for the frontend framework.
- **Module Federation 2.0**. Any bundler with MF 2.0 support is acceptable: Webpack 5, Rsbuild, Rspack, or Vite.
- Must emit `mf-manifest.json` at `https://<domain>/mf-manifest.json` exposing components and logic. Reference: https://module-federation.io/guide/basic/webpack.html.
- **React 18+**, Concurrent Mode compatible.
- `<Suspense>` support required when async loading is used.
- Component bodies must be side-effect free — **no `fetch` outside `useEffect`**.
- Dynamic imports must use `React.lazy()`.
### 2. Data & Integrations
- Consumes customer REST APIs, JSON payloads only.
- Rendered data must stay consistent with API responses (no stale state leaking into the UI).
### 3. Performance
- Must sustain **100 RPS**.
### 4. Availability & Fault Tolerance
- VMs hosting the component must be geographically distributed.
- 24/7/365 availability; recovery time ≤ 6 hours after infra is restored.
### 5. Security
- Component must be isolated — no attack surface exposed to other components of the host site.
### 6. SEO & Accessibility
- SEO optimization required.
- Render microdata: **JSON-LD** and **OpenGraph**.
- Web analytics integrations: **Yandex.Metrica, CTM, Variocube, Key-Astrom (Dynatrace)**.
### 7. Cross-Platform
- Embeddable in multiple channel apps (Web, PWA).
- Fully responsive ("fluid") layout across all screen sizes.
### 8. Logging & Monitoring
- Frontend log collection in a customer-specified format, shipped to the customer's log aggregation system.
- System event monitoring with export to a metrics aggregator.
### 9. Module Structure
- Must conform to the customer's standard remote frontend module structure for uniform deployment.
### 10. Design
- Implement against customer-provided mockups using the customer's design system.
- Must embed other customer remote components when available.
- Components must be side-effect free: no `fetch` outside `useEffect`; use the API client from context.
- Use `React.lazy()` for dynamic imports. Wrap browser-only UI such as Leaflet in `ClientOnly`.
- SignalR must stay out of SSR bundles; import `@microsoft/signalr` dynamically only.
- Read env through `getEnv()` from `@/env/index.ts`; SSR injects `window.__ENV__`.
- Keep rendered state consistent with API responses; avoid stale state leaking into UI.
- Preserve SEO/accessibility requirements, including JSON-LD and OpenGraph where relevant.
- Keep layouts fluid and responsive across screen sizes.
## Architecture
**Source structure:**
- `src/routes/` — File-based routing (React Router v7)
- `src/features/` — Feature modules (online-board, schedule, flights-map, popular-requests)
- `src/ui/` — Reusable UI primitives (never import routes/mf from here)
- `src/shared/` — Cross-cutting concerns (API client, SignalR, storage, hooks)
- `src/observability/` — Logger, metrics (OTel), analytics
- `src/i18n/` — Internationalization (9 languages)
Top-level source areas:
**Entry points:**
- `src/routes/page.tsx` — Root redirect to `/{lang}/onlineboard`
- `src/routes/layout.tsx` — Root layout with global providers
- `src/routes/[lang]/layout.tsx` — Locale-scoped layout with i18n
- `src/routes/` - file-based routing and layouts.
- `src/features/` - feature modules: online board, schedule, flights map, popular requests.
- `src/ui/` - shared UI primitives only.
- `src/shared/` - API client, storage, hooks, SignalR helpers.
- `src/observability/` - logging, metrics, analytics.
- `src/i18n/` - i18n provider and translations.
**Module Federation:**
- Remote name: `aeroflot_flights`
- Exposes: `./OnlineBoard`, `./Schedule`, `./FlightsMap`, `./PopularRequests`
- mf-manifest.json at `https://<domain>/mf-manifest.json`
Entry points:
## Critical Constraints
- `src/routes/page.tsx` redirects to `/{lang}/onlineboard`.
- `src/routes/layout.tsx` owns global providers.
- `src/routes/[lang]/layout.tsx` owns locale-scoped i18n.
1. **Side-effect-free components** — No `fetch` outside `useEffect`. API calls via `ApiClient` from context.
Module Federation:
2. **Dynamic imports** — Use `React.lazy()` for code splitting. Wrap browser-only components (Leaflet) in `ClientOnly`.
- Remote name: `aeroflot_flights`.
- Exposes: `./OnlineBoard`, `./Schedule`, `./FlightsMap`, `./PopularRequests`.
- Remote build must emit `dist/remote/mf-manifest.json`, served as `/mf-manifest.json`.
3. **SSR safety** — SignalR (`@microsoft/signalr`) is dynamically imported. Never import in SSR bundle (routes/, server/).
## Layer Boundaries
4. **Layered architecture** — Enforced by ESLint:
- `features/` → cannot import `routes/` or `mf/`
- `ui/` → cannot import `features/`, `routes/`, `mf/`
- `shared/` → cannot import `features/`, `routes/`, `mf/`, `observability/`
- `observability/` → cannot import `features/`, `routes/`, `mf/`
ESLint enforces these boundaries:
5. **Restricted imports** (ESLint rules):
- OTel SDK → use `@/observability/metrics/otel` (getMeter/getTracer)
- react-i18next → use `@/i18n/provider`
- localStorage/sessionStorage → use `@/shared/storage`
- `features/` must not import `routes/` or `mf/`.
- `ui/` must not import `features/`, `routes/`, or `mf/`.
- `shared/` must not import `features/`, `routes/`, `mf/`, or `observability/`.
- `observability/` must not import `features/`, `routes/`, or `mf/`.
6. **Environment variables** — Read via `getEnv()` from `@/env/index.ts`. SSR injects `window.__ENV__`.
Restricted imports:
## Dev Server Details
- Use `@/observability/metrics/otel` instead of importing OTel SDKs directly.
- Use `@/i18n/provider` instead of importing `react-i18next` directly.
- Use `@/shared/storage` instead of direct `localStorage` or `sessionStorage`.
- **Port 8081** — Modern.js dev server (SSR + HMR)
- **Port 8080** — `pnpm dev:full` proxy with:
- `/api/*` and `/flights/*``https://flights.test.aeroflot.ru` (via curl to bypass WAF)
- `/*` → Modern.js on 8081
## Progressive Detail
## Testing
Reach for the sections below only when the task needs them.
- **Unit tests** — Vitest (globals enabled, V8 coverage)
- **E2E tests** — Playwright (baseURL: `http://localhost:8080`)
- **Angular E2E** — Separate config for legacy app (port 4203)
### Contractual Requirements
**Coverage gates:**
- Line coverage ≥ 65%
- Bundle size (gzip) ≤ 2000 kB for remote target
- Modern.js SSR, React 18+, Module Federation 2.0 compatible output.
- `mf-manifest.json` must expose components and logic at `https://<domain>/mf-manifest.json`.
- Customer REST APIs use JSON payloads only.
- Target capacity: 100 RPS.
- Remote component must remain isolated from host components.
- Required analytics/monitoring integrations include Yandex.Metrica, CTM, Variocube, and Key-Astrom/Dynatrace.
- Frontend logs and system events must be exportable to customer aggregators.
- Implementation must follow customer mockups, design system, and standard remote module structure.
## Build Artifacts
### Dev Server
- `dist/standalone/` — SSR server (Node entrypoint)
- `dist/remote/` — MF remote with `mf-manifest.json`
- `dist/remote/static/js/` — JS bundles for bundle-size gate
- `pnpm dev` serves Modern.js SSR/HMR on port 8081.
- `pnpm dev:full` serves port 8080 and proxies:
- `/api/*` and `/flights/*` to `https://flights.test.aeroflot.ru` via curl.
- all other paths to Modern.js on 8081.
## Deployment
### Build And Deploy
- **Standalone** — Dockerfile.react (Node 24-slim, serves SSR)
- **Remote** — Dockerfile.remote (nginx serving static files)
- CI/CD: `.github/workflows/ci.yml`, `.github/workflows/deploy.yml`
- `dist/standalone/` is the Node SSR server, deployed with `Dockerfile.react`.
- `dist/remote/` is the static MF remote, deployed with `Dockerfile.remote`.
- CI/CD lives in `.github/workflows/ci.yml` and `.github/workflows/deploy.yml`.
## Commit Rules
### Current Constraints
- Never add `Co-Authored-By` lines to commit messages.
- Commit messages in English, concise, focused on "why" not "what".
- Commit autonomously when changes are complete and stable — no need to ask for permission. Group related edits into logical commits. Still ask before pushing, force-pushing, or any destructive git operation.
- Modern.js 3.x upgrade is currently blocked by `@module-federation/modern-js` ESM incompatibilities.
- React Router v7 future flags are enabled to suppress deprecation warnings.
## Gitea / Tea Command Rules
## Git And CI
- Use `tea` command to check Gitea workflow runs: `tea run list --limit 5` to see last 5 runs
- Use `tea run view <run-id>` to inspect a specific run
- Use `tea run rerun <run-id>` to re-run a failed workflow
- Do not add `Co-Authored-By` lines.
- Commit messages must be English, concise, and focused on why.
- Commit completed stable work autonomously. Ask before pushing, force-pushing, or destructive git operations.
- Use Gitea `tea` for workflow runs:
- `tea run list --limit 5`
- `tea run view <run-id>`
- `tea run rerun <run-id>`