From b5a3ab198714386d59f78c611c8e8d93bb12f148 Mon Sep 17 00:00:00 2001 From: Branimir Georgiev <66906831+braboj@users.noreply.github.com> Date: Wed, 21 Oct 2026 16:58:07 +0300 Subject: [PATCH 1/2] refactor(backend): retire backend-quality; its general rules join http (#2085) The handler, service and repository layering and its pattern catalogue are one architecture, not a rule for every backend, and leave with the template. Process lifecycle, admin processes, outbound timeouts, auth before logic and rate limits move to backend-http, the widest backend chain; the rest already lived in other backend templates. Co-Authored-By: Claude Opus 5.5 --- docs/architecture/05-building-block-view.md | 10 +-- docs/migrating-to-v3.md | 3 + templates/backend/http.md | 21 ++++++ templates/backend/quality.md | 77 --------------------- templates/manifest.yaml | 4 -- tests/baselines/template-quality.txt | 3 +- 6 files changed, 30 insertions(+), 88 deletions(-) delete mode 100644 templates/backend/quality.md diff --git a/docs/architecture/05-building-block-view.md b/docs/architecture/05-building-block-view.md index 8a1d0553..47097af0 100644 --- a/docs/architecture/05-building-block-view.md +++ b/docs/architecture/05-building-block-view.md @@ -62,13 +62,13 @@ The core tier, as the manifest states it today: - `templates/core/review.md` - `templates/core/oop.md` -Measured: 11 `[DEPENDS ON]` tokens across 7 templates name one of these -files, and 7 manifest entries name a core id in `depends_on`. Declaring one +Measured: 9 `[DEPENDS ON]` tokens across 6 templates name one of these +files, and 6 manifest entries name a core id in `depends_on`. Declaring one is redundant rather than forbidden — the seeding reaches the file either way, and the directive documents a dependency a reader would otherwise -infer. Reached by the seeding alone: `base-review`. A chain assembled by -walking the directives does not reach that set and reports nothing about it, -because nothing declares what is absent. +infer. Reached by the seeding alone: `base-review`, `base-oop`. A chain +assembled by walking the directives does not reach that set and reports +nothing about it, because nothing declares what is absent. Every top-level list of entries except `core` and `fork_core` is a section diff --git a/docs/migrating-to-v3.md b/docs/migrating-to-v3.md index d12d1498..bba4959e 100644 --- a/docs/migrating-to-v3.md +++ b/docs/migrating-to-v3.md @@ -59,6 +59,9 @@ receives nothing (ADR-051). | `quality-exemption-doc-duty`, the exit-3 and readings rules, the immutable-corpus sweep | `base-quality` | this repository's playbook | | Language porting rules; `inspect.getattr_static`; Python `__init__` and extras wording | `base-quality` | removed or neutral | | The eight-stage pipeline order, its push and tag triggers, the three-environment minimum, the post-publish deploy hook | `base-cicd` | removed; the gates, packaging once, DAST before production and artifact promotion remain | +| `backend-quality`: the handler, service and repository layering and its pattern catalogue | `backend-quality` | removed with the template; declare a stack's own architecture in a fork | +| `backend-quality`: process lifecycle, admin processes, outbound timeouts, auth before logic, rate limits | `backend-quality` | `backend-http` | +| `backend-quality`: N+1, async I/O, API deprecation, circuit breaker, outbox | `backend-quality` | already in `backend-database`, `backend-concurrency`, `backend-api`, `backend-errors`, `backend-messaging` | | The numbered-document check after concurrent merges, the first-CI-run rule for a check on its own change | `base-git` | this repository's playbook; the `check-heading-numbers` hook still ships | | The submodule update after a pin bump, the base64 bundle mask, the `.vscode` allowlist | `base-git` | removed; a neutral editor-settings rule remains | | Factory classmethods; `*-overlay.png` naming | `base-oop`, `base-measurement` | neutral rules remain | diff --git a/templates/backend/http.md b/templates/backend/http.md index 7810ea0c..b9735177 100644 --- a/templates/backend/http.md +++ b/templates/backend/http.md @@ -9,10 +9,29 @@ - Use a well-known default in development, and the port the platform assigns in production +## Process lifecycle +- Start fast — keep initialisation short (MUST) +- Shut down gracefully on `SIGTERM`: finish in-flight work, release + resources, then exit (MUST) +- Force-exit when a graceful shutdown passes its deadline +- Recover cleanly when a process is killed without warning (`SIGKILL`, + power loss) (MUST) +- Keep no state in the process; use external stores, so any instance can + be replaced + +## Admin processes +- Run one-off tasks (migrations, data fixes, REPL sessions) with the + application's code, config and dependencies (MUST) +- Commit admin scripts to the repository; never run them as ad-hoc shell + commands (MUST) +- Prefer idempotent scripts — safe to re-run +- Never run an admin task against production without a tested rollback plan + ## Handler design - Handlers are thin: decode request → call service → encode response - No business logic in handlers — delegate to a service layer - Validate all incoming request data before processing +- Set a timeout on every outbound call (HTTP clients, database queries) ## URI design - Path segments MUST be lowercase with hyphens as word separators — @@ -105,3 +124,5 @@ authorisation - Internal API endpoints SHOULD require authentication at minimum - Write endpoints MUST NOT be accessible without a valid authenticated identity +- Apply authentication and authorisation before any business logic runs +- Rate-limit public endpoints — never expose an unbounded write operation diff --git a/templates/backend/quality.md b/templates/backend/quality.md deleted file mode 100644 index b9901f96..00000000 --- a/templates/backend/quality.md +++ /dev/null @@ -1,77 +0,0 @@ -# Backend — Quality Attributes -[ID: backend-quality] -[DEPENDS ON: templates/core/quality.md, templates/core/oop.md] -[DEPENDS ON: templates/security/security.md, templates/infra/containers.md] - -## Layered architecture -- Enforce a strict handler → service → repository separation -- No database access in handlers — always go through the service layer -- No HTTP concerns in the service layer — services are framework-agnostic -- Domain logic lives in the service layer, not in models or schemas - -## Design patterns - -Prefer these patterns for backend concerns: - -- **Repository** — abstract all data access behind a repository interface; - the service layer never constructs queries directly -- **Service layer** — encapsulate business logic in service objects that - hold their injected collaborators and no request state; one service per - domain aggregate -- **Unit of Work** — coordinate multiple repository operations in a single - transaction; commit or roll back as one atomic unit -- **Factory / Factory Method** — centralise object construction, especially - for domain objects with complex invariants -- **Strategy** — swap algorithms or business rules (pricing, validation, - export format) at runtime without modifying the caller -- **Observer / Event** — decouple producers from consumers for domain events - (user registered, order placed); use an internal event bus or message queue -- **Circuit Breaker** — wrap all outbound calls to external services; - fail fast and recover gracefully rather than cascading timeouts -- **Outbox** — when publishing an event must be atomic with a DB write, - write to an outbox table in the same transaction and relay asynchronously -- **CQRS** — separate read models from write models when query and command - requirements diverge significantly; do not apply by default - -## Disposability - -- Processes MUST start fast — minimize initialization time -- Processes MUST shut down gracefully on `SIGTERM` — finish - in-flight work, release resources, then exit -- Set a shutdown timeout — if graceful shutdown exceeds the - deadline, force-exit -- Design for crash safety — the system MUST recover cleanly if - a process is killed without warning (`SIGKILL`, power loss) -- Do not store state in-process — use external stores (database, - cache, queue) so processes are disposable and replaceable - -## Admin processes - -- One-off tasks (migrations, data fixes, REPL sessions) MUST run - in the same environment as the application — same code, same - config, same dependencies -- Admin scripts MUST be committed to the repository — not run - from ad-hoc shell commands -- Prefer idempotent scripts — safe to re-run without side effects -- Never run admin tasks directly against production without a - tested rollback plan - -## Security -[EXTEND: security-input] - -- Rate-limit public endpoints — never expose unbounded write operations -- Apply authentication and authorisation before any business logic - executes - -## Performance -- Prefer async I/O for network-bound operations -- Cache only when there is a measured need — document cache invalidation - strategy -- Avoid N+1 queries — use eager loading or batch fetching -- Set timeouts on all outbound calls (HTTP clients, DB queries) - -## API stability -- Never remove or rename a field in a response without a deprecation period -- Increment the API version (`/v2/`) for breaking changes — keep the old version - alive -- Document deprecated endpoints; set a removal date before retiring them diff --git a/templates/manifest.yaml b/templates/manifest.yaml index d63d95e3..b7edcf9f 100644 --- a/templates/manifest.yaml +++ b/templates/manifest.yaml @@ -170,10 +170,6 @@ backend: file: templates/backend/monitoring.md description: Key metrics, thresholds, alerts, dashboards, incidents depends_on: [backend-observability] - - id: backend-quality - file: templates/backend/quality.md - description: Layered architecture, security, performance, API stability - depends_on: [base-quality, base-oop, base-security, base-containers] stacks: - id: stack-fixture file: templates/fixture/stack.md diff --git a/tests/baselines/template-quality.txt b/tests/baselines/template-quality.txt index f8ab5f40..0cbfe679 100644 --- a/tests/baselines/template-quality.txt +++ b/tests/baselines/template-quality.txt @@ -11,13 +11,12 @@ templates/backend/edge.md 89.7 templates/backend/errors.md 91.7 templates/backend/features.md 92.2 templates/backend/grpc.md 96.1 -templates/backend/http.md 96.4 +templates/backend/http.md 97.8 templates/backend/jobs.md 97.2 templates/backend/messaging.md 96.8 templates/backend/microservices.md 93.5 templates/backend/monitoring.md 98.5 templates/backend/observability.md 96.6 -templates/backend/quality.md 98.3 templates/backend/webhooks.md 86.9 templates/core/agents.md 100.0 templates/core/config.md 99.3 From 4ea6d3b0018bb1a8c84637d57384bce6feb12f04 Mon Sep 17 00:00:00 2001 From: Branimir Georgiev <66906831+braboj@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:03:18 +0300 Subject: [PATCH 2/2] docs(changelog): note #2102 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 939946d9..22a8108d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ Releases up to 2.63.0 are listed in check-harness rules ([#2082]) - The git template drops its submodule, numbered-document and base64 rules and the .vscode allowlist ([#2093]) +- The backend-quality template is retired; its general rules move to the HTTP + template ([#2102]) ### Added @@ -197,6 +199,7 @@ Releases up to 2.63.0 are listed in [#2096]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2096 [#2097]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2097 [#2098]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2098 +[#2102]: https://github.com/solid-ai-dev/solid-ai-templates/pull/2102 ## [2.90.0] - 2026-09-12