From 421d004faf44c06e5ab6635dc04ecd4efb781b00 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Fri, 12 Jun 2026 10:00:02 +0300 Subject: [PATCH] Deduplicate overlapping rules across contracts Each rule now has one owning contract; others point to it: validation and multi-step rules live in forms-validation (modal-workflows references them), pagination metadata lives in go-api (table-management references it), the async task flow lives in go-background-tasks (go-api references it), backup git-safety checks live in backup-management (go-database references it). Remove the leftover Vapor/Aqua baseline mention and stale kit/patterns paths, compress the batch-file-upload ADR narrative, and drop content-free pattern READMEs. Co-Authored-By: Claude Fable 5 --- rules/patterns/batch-file-upload/contract.md | 40 ++++--------------- rules/patterns/bom-decomposition/README.md | 19 --------- rules/patterns/controls-selection/README.md | 13 ------ rules/patterns/controls-selection/contract.md | 10 ++--- rules/patterns/forms-validation/README.md | 12 ------ rules/patterns/forms-validation/contract.md | 10 ++++- rules/patterns/go-api/contract.md | 13 ++---- rules/patterns/go-code-style/contract.md | 4 +- rules/patterns/go-database/contract.md | 3 +- rules/patterns/import-export/README.md | 13 +----- rules/patterns/modal-workflows/README.md | 9 ----- rules/patterns/modal-workflows/contract.md | 17 +++----- rules/patterns/table-management/contract.md | 10 ++--- 13 files changed, 36 insertions(+), 137 deletions(-) delete mode 100644 rules/patterns/controls-selection/README.md delete mode 100644 rules/patterns/forms-validation/README.md delete mode 100644 rules/patterns/modal-workflows/README.md diff --git a/rules/patterns/batch-file-upload/contract.md b/rules/patterns/batch-file-upload/contract.md index c896ee5..1075420 100644 --- a/rules/patterns/batch-file-upload/contract.md +++ b/rules/patterns/batch-file-upload/contract.md @@ -1,30 +1,16 @@ # Contract: Batch File Upload -Version: 1.0 +Version: 1.1 ## Purpose -ADR: стратегия загрузки большого числа файлов через multipart-запросы -без переработки серверного pipeline и без скрытых лимитов. +Загрузка большого числа файлов одним multipart-запросом упирается в скрытые лимиты: +количество parts, размер тела запроса (413), таймауты соединения. Поэтому клиент делит +список файлов на батчи фиксированного размера и отправляет каждый батч отдельным +multipart-запросом. Цена решения — больше round-trips и, без агрегации, несколько +выходных файлов. ---- - -## ADR - -**Дата:** 2026-03-01 -**Статус:** Accepted - -### Контекст - -Клиент должен загрузить список файлов на сервер для обработки. -Загрузка всех файлов одним multipart-запросом упирается в скрытые лимиты: -количество parts, размер тела запроса (413), таймауты соединения. -Переработка серверного pipeline под стриминговую загрузку — отдельная дорогостоящая задача. - -### Решение - -Клиент делит список файлов на батчи фиксированного размера и отправляет каждый батч -отдельным multipart-запросом. +## Решение - Размер батча определяется константой `MAX_FILES_PER_BATCH` (выбирается проектом). - Батчи считаются по **числу файлов**, не только по байтам. @@ -33,18 +19,6 @@ ADR: стратегия загрузки большого числа файло - Каждый батч производит отдельный downloadable артефакт, либо агрегируется на финальном шаге — решение принимается на уровне проекта. -### Последствия - -**Плюсы:** -- Избегаем скрытых лимитов на количество multipart parts -- Снижаем риск таймаутов и ошибок 413 -- Не требует немедленной переработки серверного parser pipeline - -**Минусы:** -- Больше round-trips (N батчей = N запросов) -- Несколько выходных файлов если артефакты не агрегируются -- Более долгий end-to-end UX для пользователя - --- ## Правила реализации diff --git a/rules/patterns/bom-decomposition/README.md b/rules/patterns/bom-decomposition/README.md index 1a912a6..abbda98 100644 --- a/rules/patterns/bom-decomposition/README.md +++ b/rules/patterns/bom-decomposition/README.md @@ -27,25 +27,6 @@ Project-specific aliases are acceptable if the semantics stay identical: - `component_mappings` -> `lot_mappings` - `quantity_per_item` -> `quantity_per_pn` -## Persistence Example - -```json -{ - "vendor_spec": [ - { - "sort_order": 10, - "vendor_partnumber": "ABC-123", - "quantity": 2, - "description": "Bundle", - "lot_mappings": [ - { "lot_name": "LOT_CPU", "quantity_per_pn": 1 }, - { "lot_name": "LOT_RAIL", "quantity_per_pn": 1 } - ] - } - ] -} -``` - ## Wrong Shape ```json diff --git a/rules/patterns/controls-selection/README.md b/rules/patterns/controls-selection/README.md deleted file mode 100644 index 79408a8..0000000 --- a/rules/patterns/controls-selection/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Controls + Selection Pattern - -Canonical interactive controls for server-rendered admin/list pages: - -- button hierarchy (primary / secondary / danger / quiet / disabled) -- segmented filters -- row checkboxes + select-all-visible semantics -- bulk-action bar with explicit preview/confirm steps -- status badges for list rows and workflow state - -This pattern standardizes control language and interaction shape while leaving branding and -domain terminology to the host project. - diff --git a/rules/patterns/controls-selection/contract.md b/rules/patterns/controls-selection/contract.md index 18070a1..4676e8e 100644 --- a/rules/patterns/controls-selection/contract.md +++ b/rules/patterns/controls-selection/contract.md @@ -1,20 +1,17 @@ # Contract: Controls + Selection -Version: 1.0 +Version: 1.1 ## Shared Base -- This pattern inherits the shared `table-management` contract: - `kit/patterns/table-management/contract.md`. +- This pattern inherits the shared `table-management` contract. +- Visual styling comes from `web-visual-baseline`. - Reuse shared toolbar/table/icon geometry from the base contract first, then define only controls-specific additions below. ## Buttons - Use a small stable button taxonomy: `primary`, `secondary`, `ghost`, `danger`, `disabled`. -- The canonical visual baseline for demo/scaffold examples is the active dual baseline used in the - demo/scaffold (`Vapor Soft` / `Vapor Night`, system-selected). A frozen Aqua snapshot bundle may - be kept for archival reference, but examples should follow the active baseline. - Destructive actions (`archive`, `delete`, `remove`) must use danger styling and explicit labels. - Button text should describe the action outcome, not implementation detail. - Buttons are text-first; icons are optional and must not replace labels on primary/danger actions. @@ -26,7 +23,6 @@ Version: 1.0 - Header checkbox semantics must be explicit: - select visible rows only, or - select all rows in query scope (must be clearly labeled) -- Selection summary must show count (`N selected`) near bulk actions. - In paginated views, the UI should distinguish selection on the current page from selection across the filtered/query scope. - Selection state should survive pagination/filter navigation via explicit state (query params, server session, or another deterministic mechanism). - Same-page interactions should preserve reading position (module anchor pattern is preferred in canonical server-rendered flows). diff --git a/rules/patterns/forms-validation/README.md b/rules/patterns/forms-validation/README.md deleted file mode 100644 index c691da6..0000000 --- a/rules/patterns/forms-validation/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Forms + Validation Pattern - -Canonical patterns for server-rendered form workflows in Go web applications: - -- tabbed / mode-switched forms -- datalist/autocomplete suggestions -- inline validation messages -- review / confirm step before submit -- explicit reset and error handling states - -This pattern standardizes interaction flow and validation UX, not domain-specific field sets. - diff --git a/rules/patterns/forms-validation/contract.md b/rules/patterns/forms-validation/contract.md index b36eb25..8cea7f2 100644 --- a/rules/patterns/forms-validation/contract.md +++ b/rules/patterns/forms-validation/contract.md @@ -1,6 +1,9 @@ # Contract: Forms + Validation + Suggestions -Version: 1.0 +Version: 1.1 + +This contract owns validation UX and multi-step flow rules for all form surfaces, +including modals (`modal-workflows` adds only modal-specific mechanics). ## Form Structure @@ -10,8 +13,10 @@ Version: 1.0 ## Validation +- Validate on submit server-side. Client-side validation is optional progressive enhancement only. - Surface validation errors inline near fields and in a form-level summary when helpful. -- Validation messages must be human-readable and action-oriented. +- Validation messages must be human-readable and action-oriented: "Serial number is required" — + not "serial_number: cannot be null". - Do not hide required-field errors behind generic submit failures. ## Multi-Step Flow @@ -26,6 +31,7 @@ Recommended stages: Rules: - Users must be able to return from review to edit without losing entered values. +- The confirm step must summarise what will happen before a destructive or irreversible action. - Destructive or irreversible actions require explicit confirmation. - Query- or state-driven step transitions should be deterministic and testable. diff --git a/rules/patterns/go-api/contract.md b/rules/patterns/go-api/contract.md index aac1493..122126e 100644 --- a/rules/patterns/go-api/contract.md +++ b/rules/patterns/go-api/contract.md @@ -1,6 +1,6 @@ # Contract: REST API Conventions (Go Web Applications) -Version: 1.0 +Version: 1.1 ## URL Naming @@ -82,12 +82,5 @@ GET /api/db-status → 200 {"ok": true} or 500 {"ok": false, "error": "..."} ## Async Actions -For long-running operations return immediately with a task reference: - -``` -POST /api/pricelists/create → 202 {"task_id": "abc123"} -GET /api/tasks/abc123 → 200 {"status": "running", "progress": 42, "message": "Processing..."} -GET /api/tasks/abc123 → 200 {"status": "success", "result": {...}} -``` - -See `go-background-tasks/contract.md` for full task contract. +Long-running operations return `202 {"task_id": "..."}` immediately and the client polls +`GET /api/tasks/:id`. Full flow, statuses, and task struct: `go-background-tasks` contract. diff --git a/rules/patterns/go-code-style/contract.md b/rules/patterns/go-code-style/contract.md index 7de4eb9..0fd0120 100644 --- a/rules/patterns/go-code-style/contract.md +++ b/rules/patterns/go-code-style/contract.md @@ -1,6 +1,6 @@ # Contract: Go Code Style and Project Conventions -Version: 1.1 +Version: 1.2 ## Source Text and Comments @@ -11,7 +11,7 @@ Version: 1.1 ## Logging -See `kit/patterns/go-logging/contract.md` for full rules. +See the `go-logging` contract for full rules. Summary: use `slog`, log to stdout/stderr (binary console), never to browser console. diff --git a/rules/patterns/go-database/contract.md b/rules/patterns/go-database/contract.md index b7d5c1b..b1e0316 100644 --- a/rules/patterns/go-database/contract.md +++ b/rules/patterns/go-database/contract.md @@ -1,6 +1,6 @@ # Contract: Database Patterns (Go / MySQL / MariaDB) -Version: 1.9 +Version: 1.10 See `README.md` for examples, migration snippets, and Docker test commands. @@ -20,7 +20,6 @@ See `README.md` for examples, migration snippets, and Docker test commands. - Backup storage, retention, archive format, and restore-readiness must follow `backup-management`. - Before applying any unapplied migrations, take and verify a full DB backup. - Before applying a migration step that changes a table, take a targeted backup of each affected table. -- Before writing any backup, verify that the output path resolves outside the git worktree and is not tracked or staged in git. - If any migration step in a session fails, roll back all steps applied in that session in reverse order. - If rollback is not sufficient, restore from the targeted backup taken before the failing step. - After rollback or restore, the DB must be back in the same state it had before the session started. diff --git a/rules/patterns/import-export/README.md b/rules/patterns/import-export/README.md index 4937643..526b90d 100644 --- a/rules/patterns/import-export/README.md +++ b/rules/patterns/import-export/README.md @@ -1,15 +1,6 @@ -# Import / Export Pattern +# Import / Export Pattern Notes -Canonical file transfer UX patterns for Go web applications: - -- file import forms (CSV/JSON and similar) -- validation preview tables before confirm -- confirm step with human-readable summary -- export controls (format + scope + options) -- predictable file download behavior and filenames - -This pattern covers UI and UX contracts. Business-specific validation and file schemas remain in -the host project's own architecture docs. +This file keeps examples. The normative rules live in `contract.md`. ## Export Handler Sketch diff --git a/rules/patterns/modal-workflows/README.md b/rules/patterns/modal-workflows/README.md deleted file mode 100644 index e289e40..0000000 --- a/rules/patterns/modal-workflows/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Modal Workflow Pattern - -This pattern package captures modal-based create/edit/remove workflows for server-rendered Go -web UIs. - -Synthesis sources: - -- detailed enterprise UI interaction contracts -- operational admin workflows in Go web apps diff --git a/rules/patterns/modal-workflows/contract.md b/rules/patterns/modal-workflows/contract.md index 1c9d2db..b204f12 100644 --- a/rules/patterns/modal-workflows/contract.md +++ b/rules/patterns/modal-workflows/contract.md @@ -1,6 +1,6 @@ # Contract: Modal Workflows -Version: 1.0 +Version: 1.1 ## State Machine @@ -29,11 +29,8 @@ closed → open → submitting → success | error ## Validation -- Validate on submit server-side. Client-side validation is optional progressive enhancement only. -- Show field-level errors inline below each field. -- Show a form-level error summary at the top if multiple fields fail. -- Error messages must be human-readable and action-oriented: "Serial number is required" — not - "serial_number: cannot be null". +Validation UX follows the `forms-validation` contract (server-side on submit, inline field +errors, form-level summary, human-readable messages). ## htmx Pattern (server-rendered modals) @@ -44,15 +41,13 @@ POST /api/entity → 200 OK + HX-Trigger: "entitySaved" (success) ``` - On success: server sends `HX-Trigger` header, JS listener closes modal and refreshes list. -- On validation error: server re-renders the form partial with inline errors (422). +- On validation error: server re-renders the form partial with inline errors (422, per `go-api`). - On server error: show generic error toast, log full error server-side. -- Do not use `200 OK` for validation errors — use `422` so htmx can differentiate. ## Multi-Step Modals -Use only when the workflow genuinely requires staged input (e.g. import preview → confirm). +Staged flows follow the `forms-validation` multi-step rules. Modal-specific: +- Use only when the workflow genuinely requires staged input (e.g. import preview → confirm). - Show a step indicator (Step 1 of 3). -- Back button must restore previous step values. -- Final confirm step must summarise what will happen before the destructive/irreversible action. - Single-step edits must NOT be split into multi-step without good reason. diff --git a/rules/patterns/table-management/contract.md b/rules/patterns/table-management/contract.md index 312f76e..6db5950 100644 --- a/rules/patterns/table-management/contract.md +++ b/rules/patterns/table-management/contract.md @@ -1,6 +1,6 @@ # Contract: Table Management (Shared) -Version: 1.0 +Version: 1.1 ## Scope @@ -91,11 +91,9 @@ Canonical mapping: ## Pagination Rules - Pagination is server-side. Never load all rows and paginate client-side. -- URL query parameters carry page state: `?page=2&per_page=50`. - - `page` is 1-based. - - `per_page` defaults to a fixed project constant (e.g. 50); user may change it from a fixed set - (25 / 50 / 100). -- The server response includes: `total_count`, `page`, `per_page`, `total_pages`. +- Query parameters and list response metadata follow the `go-api` contract. +- `page` is 1-based; `per_page` defaults to a fixed project constant (e.g. 50) and may be + changed from a fixed set (25 / 50 / 100). - Display: "Showing 51–100 of 342" — always show the range and total. - Prev/Next buttons are disabled (not hidden) at the boundary pages. - Direct page-number input is optional; if present it clamps to `[1, total_pages]` on blur.