fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
175
replit.md
Normal file
175
replit.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Overview
|
||||
|
||||
This is a multitenant corporate iistwin platform with a React frontend and an Express backend, designed to provide organizations with independent management of users, projects, and workflows on shared infrastructure. It ensures data isolation, scalability, and security, offering real-time communication and efficient task handling. Key capabilities include custom JS pages, data tables, advanced workflow transitions with conditional approvals, hierarchical subtasks, inline editable tables, and an event-driven notification system.
|
||||
|
||||
# User Preferences
|
||||
|
||||
Preferred communication style: Simple, everyday language.
|
||||
Preferred language: Russian — always respond in Russian, no exceptions.
|
||||
|
||||
# System Architecture
|
||||
|
||||
## Frontend
|
||||
The frontend uses React with TypeScript and Vite, employing a component-based architecture with `shadcn/ui`, Radix UI, and Tailwind CSS. Wouter handles routing, TanStack Query manages server state, and React Hook Form with Zod is used for form handling. Authentication is context-based using JWT tokens.
|
||||
|
||||
## Backend
|
||||
The backend is built with Express.js, featuring a layered architecture (API, Service, Data Access) and Drizzle ORM for database abstraction. Custom middleware enforces tenant isolation, authentication, and request validation.
|
||||
|
||||
## Authentication & Authorization
|
||||
JWT-based authentication uses access and refresh tokens. Role-based access (Admin, User) is enforced, and bcrypt secures passwords.
|
||||
|
||||
## Super Admin System
|
||||
A separate system-level super admin panel exists at `/superadmin` (login at `/superadmin/login`). Super admins are stored in the `super_admins` table (no organizationId — system-level users). They authenticate via a separate JWT with `{ isSuperAdmin: true, audience: 'workflow-superadmin' }` checked by `requireSuperAdmin` middleware. The panel shows all organizations with stats (users, tasks, last activity) and allows toggling organization access. First super admin is created via `POST /api/superadmin/seed` (protected by optional `SUPERADMIN_SEED_TOKEN` env var).
|
||||
|
||||
## Multitenancy
|
||||
Tenant isolation is implemented at the database (via `organizationId`), API (middleware filtering), and authentication levels.
|
||||
|
||||
## Database
|
||||
A PostgreSQL database with Drizzle ORM is used, featuring core entities like Organizations, Users, and User Sessions with serial primary keys and foreign key relationships.
|
||||
|
||||
## Security & Legal Compliance
|
||||
|
||||
### HTTP Security Headers
|
||||
`helmet` middleware is configured in `server/index.ts` with a Content Security Policy that allows `unsafe-eval` and `unsafe-inline` for the Monaco editor and Babel runtime. `crossOriginEmbedderPolicy` is disabled to support iframe embeds. `frameguard` (X-Frame-Options) is disabled and `frame-ancestors` allows `https://*.replit.dev`, `https://*.repl.co`, `https://*.replit.com` so the app can be embedded in the Replit IDE preview and Canvas.
|
||||
|
||||
**HSTS and upgrade-insecure-requests** are conditionally enabled per-request when the server detects it is behind an HTTPS reverse proxy. Detection uses two conditions (either is sufficient):
|
||||
1. `HTTPS_PROXY=true` env var — static override, set in docker-compose or deployment config.
|
||||
2. `X-Forwarded-Proto: https` request header — sent automatically by Nginx/Traefik/Caddy when proxying HTTPS traffic.
|
||||
|
||||
When either condition is true: `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload` and CSP `upgrade-insecure-requests` are added to the response.
|
||||
When neither is true (plain HTTP dev/local): these headers are omitted.
|
||||
|
||||
### Personal Data (152-ФЗ Compliance)
|
||||
- Consent checkbox with link to `/privacy-policy` is required on both registration forms (Register.tsx and InviteRegister.tsx)
|
||||
- Privacy Policy page at `/privacy-policy` (PrivacyPolicy.tsx) explains data processing in accordance with Russian Federal Law 152-ФЗ
|
||||
- Known remaining gaps (for production deployments): DB localization to Russian hosting, replace SendGrid with a Russian email provider, add user data export/deletion self-service UI
|
||||
|
||||
### Remaining xlsx Vulnerabilities
|
||||
The `xlsx` (SheetJS) package has 1 high + 7 moderate known vulnerabilities with no fix available upstream. This affects the Excel import/export feature for data tables.
|
||||
|
||||
## Real-time Communication
|
||||
The system includes real-time chat with optimistic updates and `@mentions`. Server-Sent Events (SSE) provide instant read receipts and `task_updated` events, with polling as a fallback.
|
||||
|
||||
## Server-Side TTL Cache
|
||||
A lightweight in-memory TtlCache (`server/utils/cache.ts`) is used for frequently accessed data like forms and minimal task lists, with a 60-second TTL and invalidation on data changes.
|
||||
|
||||
## Custom Data Tables
|
||||
Organizations can create custom data tables with named columns, inline editing, three-tier access control, Excel import/export, and integration as a form field type.
|
||||
|
||||
## Workflow Transitions
|
||||
Forms support customizable statuses and transitions with conditional approvals, dynamic approver assignment, and real-time UI updates via SSE.
|
||||
|
||||
## Task Tabs System
|
||||
Task fields can be organized into configurable tabs within the form editor, supporting 'fields' or 'table' types. A modular plugin system allows for new tab types and custom declarative tab modules (JSON configurations). These modules support various component types, including `info_panel`, `image_gallery`, `chart`, `tabs`, `layout`, and `formula`, allowing user input storage in `task_tab_values`.
|
||||
|
||||
## JS Code Editor for Custom Tabs
|
||||
A `js_component` module type enables writing arbitrary React+JSX code in the browser using the Monaco Editor. Code is executed in a sandboxed environment via `@babel/standalone` and `new Function()`, with a `ctx` object providing access to React, UI components, API calls, user info, task data, and messaging functions.
|
||||
|
||||
## Regular Tables
|
||||
Forms can include 'table' type tabs, providing customizable tables with inline editing, various column types (text, number, date, select, table reference), resizable columns, and compact display.
|
||||
|
||||
## Hierarchical Subtasks
|
||||
Tasks support unlimited nesting of subtasks with parent-child relationships, automatic numbering, depth tracking, and UI navigation.
|
||||
|
||||
## Event-Driven Notification System
|
||||
An event-driven notification system allows users to subscribe to events like `task.created` or `task.status.changed`, delivering notifications via in-app alerts, email, and real-time push via SSE. `@mentions` always trigger notifications.
|
||||
|
||||
## Billing System
|
||||
|
||||
A multi-tenant billing system allows super admins to manage organization balances and pricing. Key features:
|
||||
|
||||
- `organization_billing` table: per-org settings (balance, pricePerUser, currency, nextBillingDate, blockedAt)
|
||||
- `billing_transactions` table: credit/debit transaction history with descriptions
|
||||
- `billingBlocked` flag on organizations for fast access checks
|
||||
- Billing cycle worker: runs every 24h, charges `activeUsers × pricePerUser`, blocks orgs with insufficient balance
|
||||
- Super admin panel: view/edit billing settings, top up balance, unblock orgs, view transaction history
|
||||
- Org admin billing page at `/billing`: read-only view of balance, active users, estimated charge, transaction history
|
||||
- `billingBlocked` check in `authenticateToken` middleware returns HTTP 402 for non-whitelisted endpoints
|
||||
- Whitelist: `/api/auth/`, `/api/superadmin/`, `/api/billing/`, `/api/health`
|
||||
- Layout.tsx shows a blocking overlay when `billingBlocked=true` (except on `/billing` route itself)
|
||||
- Billing link added to the sidebar dropdown for admins
|
||||
|
||||
## File Upload System
|
||||
Form fields of type `file` allow users to upload files to tasks. The system supports two storage backends selected automatically via environment variables:
|
||||
|
||||
**Local disk mode (default/Replit/dev):** Files saved to `uploads/`, served via `express.static` at `/uploads/`. No extra config needed.
|
||||
|
||||
**S3/MinIO mode (production/Docker):** Activated when `MINIO_ENDPOINT` env var is set. Files uploaded to MinIO S3 bucket via `@aws-sdk/client-s3`. Served via proxy endpoint `GET /api/files/:key` (streams from S3). File deletion uses `DeleteObjectCommand`. Helper: `server/utils/s3.ts`.
|
||||
|
||||
Both modes: upload endpoint `POST /api/upload` (multer, 10 MB limit, MIME-type allowlist), protected by `authenticateToken`. Stored field values are JSONB objects `{ url, name, size }`. File deletion correctly handles both single files and arrays — only removes files missing from the new value (`deleteRemovedFiles`).
|
||||
|
||||
**Docker deployment:** `docker-compose.yml` has `with-minio` profile adding MinIO (ports 9000/9001) and WebDAV via rclone (port 8080) for file browsing from Windows Explorer/Finder. See `DOCKER.md` for full instructions.
|
||||
|
||||
## Task Audit Log
|
||||
A chronological history of all task changes is stored in `task_audit_log`, tracking actions like creation, status changes, updates, and field value modifications. This log is accessible via an API and displayed in the UI as a timeline.
|
||||
|
||||
## Inline Editing of Task Form Fields
|
||||
Custom form field values can be edited directly on the task detail page. This feature provides type-specific editors, save/cancel actions, and records changes in the `task_audit_log`.
|
||||
|
||||
## Task Reminders System
|
||||
Tasks support scheduled reminders with flexible recipient configuration (individual users or roles). A background worker processes and sends these reminders via the notification system.
|
||||
|
||||
## Push Notifications Infrastructure
|
||||
The system includes infrastructure for mobile push notifications with tenant isolation, using `device_tokens` for FCM/APNs, `user_presence` for online status, and a push queue for offline users.
|
||||
|
||||
### VAPID Keys for Web Push
|
||||
Web push notifications require stable VAPID keys. Without them, new keys are generated on every server restart, invalidating all existing browser push subscriptions.
|
||||
|
||||
**Setup (one-time):** Generate permanent keys and set them as environment secrets:
|
||||
```bash
|
||||
npx web-push generate-vapid-keys
|
||||
```
|
||||
Set the output as `VAPID_PUBLIC_KEY` and `VAPID_PRIVATE_KEY` in your environment secrets (Replit Secrets tab or `.env` for Docker). If keys are missing, the server logs a warning and generates temporary keys for that session only.
|
||||
|
||||
See `DOCKER.md` → "Генерация VAPID-ключей для веб-пушей" for Docker deployment instructions.
|
||||
|
||||
## Mobile UI Adaptations
|
||||
The UI adapts for mobile devices (screen width <768px), with chat always in a separate tab and a visible tab selector.
|
||||
|
||||
## Progressive Web App (PWA)
|
||||
The system supports PWA installation, offering offline access and push notifications via `manifest.json`, a Service Worker (`sw.js`), and a PWA Install Button.
|
||||
|
||||
## Global Fields System
|
||||
Reusable global fields with pre-filled settings (type, options, validation) can be used across all organization forms. They serve as templates, and changes to global fields do not affect existing form fields.
|
||||
|
||||
## Automations System
|
||||
JavaScript automations stored in the `automations` table allow server-side code execution in a Node.js `vm` sandbox in response to triggers (`manual`, `task.created`, `task.status_changed`). A `ctx` object provides logging and access to forms and tasks.
|
||||
|
||||
## JS Layout Editor for Task Detail Page
|
||||
Admins can write custom React/JSX components to replace the default field display on any task detail page. The code is stored in `forms.detailLayoutCode` and edited via a Monaco editor in the FormEditor.
|
||||
|
||||
## Task Relations System
|
||||
Many-to-many task relations are stored in `task_relations`, created automatically via "task" type fields or manually via a "Link" button in chat. Related tasks are displayed in a dedicated UI tab, showing a flattened list grouped by form.
|
||||
|
||||
## Performance Optimizations
|
||||
Optimizations include aggregated API endpoints, React Query caching, server-side pagination with sorting, strategic database indexing, and server-side computation of user `fullName`.
|
||||
|
||||
# External Dependencies
|
||||
|
||||
## Database
|
||||
- **Neon Database**: Serverless PostgreSQL database.
|
||||
- **Drizzle ORM**: Type-safe database toolkit.
|
||||
|
||||
## Authentication & Security
|
||||
- **JWT**: JSON Web Tokens.
|
||||
- **bcrypt**: Password hashing.
|
||||
- **Express rate limiter**: For API protection.
|
||||
|
||||
## Email Services
|
||||
- **SendGrid**: Email delivery service.
|
||||
|
||||
## UI Frameworks
|
||||
- **Radix UI**: Unstyled, accessible UI primitives.
|
||||
- **Tailwind CSS**: Utility-first CSS framework.
|
||||
- **shadcn/ui**: Pre-built component library.
|
||||
|
||||
## Development Tools
|
||||
- **Vite**: Build tool and development server.
|
||||
- **TypeScript**: Static type checking.
|
||||
|
||||
## Code Editor & JS Runtime
|
||||
- **@monaco-editor/react**: Monaco Editor for in-browser JavaScript editing.
|
||||
- **@babel/standalone**: In-browser Babel for JSX transformation.
|
||||
|
||||
## HTML Sanitization
|
||||
- **dompurify**: For safe HTML rendering.
|
||||
Reference in New Issue
Block a user