Skip to content

Latest commit

 

History

History
127 lines (102 loc) · 11.3 KB

File metadata and controls

127 lines (102 loc) · 11.3 KB

LearnStack Engineering Standards

This directory contains the engineering rules that apply across the LearnStack codebase. Architecture docs (docs/architecture/) explain what we are building; standards explain how we build it.

How to Use This Directory

  • Author-side: before opening a PR, skim the standards that touch your change.
  • Reviewer-side: reference standards in review comments rather than re-litigating preferences.
  • Newcomer-side: read 00-principles.md first; the rest is reference material.
  • Disagreement: propose a change via PR against the standard itself. Standards are versioned documents, not folklore.

Index

# Document Scope
00 Principles The handful of beliefs every other standard descends from.
01 Architecture Standards Module boundaries, dependency direction, ports & adapters, aggregate ownership.
02 Backend Coding Standards C# / .NET style, async, nullability, records, MediatR, EF Core.
03 Frontend Coding Standards TypeScript / React / Next.js style, components, hooks, data fetching.
04 API Design Standards REST, Problem Details, pagination, idempotency, versioning.
05 Database Standards Schema conventions, migrations, indexing, tenant-aware patterns.
06 Testing Standards Unit / integration / architecture / E2E / contract tests; pyramid; coverage targets.
07 Frontend Architecture Standards App Router layout, server vs client components, tenant context, SDK shape.
08 Localization Standards i18n rules for strings, content, URLs, SEO, formatting.
09 Error Handling Standards Exception hierarchy, Problem Details, frontend error boundaries, user-facing copy.
10 Observability Standards Logging, tracing, metrics, correlation, redaction.
11 Security Standards Auth, tenant isolation enforcement, OWASP, secrets, file uploads, headers.
12 Infrastructure Standards Docker, CI/CD, environments, configuration, deployment.
13 Documentation Standards ADRs, code comments, diagrams, doc style.
14 Git Workflow Standards Branching, commits, PRs, reviews.
15 Performance Standards Budgets, caching, query shape, frontend perf.
16 Accessibility Standards WCAG targets, semantic HTML, keyboard, screen readers.
17 Code Review Standards What to look for, what not to block on, etiquette. Zero-tolerance blockers and author self-review gate.
18 Audit Coverage Standards Which operations must be audited; payload contract; retention; per-module classification matrix.
19 Permissions Standards {module}.{resource}.{action} naming, closed action set, registry pattern, matrix template, built-in roles.
20 Infrastructure Stack Standards Demand-gated building blocks, the foundation ports (IEventBus, ICacheService, ISecretProvider), APISIX gateway, Hub contract surface + its two invariants, entitlement projection, outbox/inbox usage.
21 Architecture Tests + Analyzers Catalogue Single source of truth for the identifier, assertion, status, and source ADR / standard of every non-skippable architecture test or Roslyn analyzer. Cross-link target so renames touch one place.

Status of Each Standard

Standards have one of three states:

  • Active. Currently enforced; PRs must comply. There is code, tooling, or a live process that the standard governs today.
  • Adopted. Agreed and binding on the code that will implement it — but that code does not exist yet, so nothing enforces it beyond review.
  • Draft. Proposed; open for discussion.

The rule that makes the model mean something

A standard with no implementing code is Adopted, not Active.

Each document declares its state at the top, and until 2026-08-08 all twenty-two declared Active — including standards governing endpoints, migrations, permissions and audit rows that do not exist. A three-state model whose every member sits in one state is decorative: it tells a reader nothing, and it quietly overstates how much of the corpus is load-bearing.

"Adopted" is not a weaker commitment. It is the honest one. It says: this is the rule the implementing PR must satisfy, and there is nothing standing between a violation and main except a reviewer who remembers. That is exactly the situation in which a reviewer most needs to know.

Promotion Adopted → Active happens in the PR that lands the enforcement — the migration, the endpoint, the analyzer, the architecture test — not in a separate bookkeeping pass.

Honest status today

The table below is the current, accurate state as of 2026-08-08, at HEAD with Phase 02a Packets 0–3 shipped.

The individual documents still declare Active in their own headers. Reconciling the twenty-two status lines with this table is a Phase 02a Packet 10 deliverable, landed together with the architecture-test reconciliation so the two views of "what is actually enforced" change in one commit. Until that lands, this table wins.

# Standard Status What does or does not enforce it today
00 Principles Active Governs every PR and every ADR; principles 1, 16 and 17 are already deciding live scope questions.
01 Architecture Standards Active Module layout shipped; ModuleDomain_DoesNotDependOn_* and the planted-violation meta-test are green.
02 Backend Coding Active MediatR pipeline, Result<T>, IClock, the LS0001 analyzer and the pipeline-order test all ship. Its EF Core and domain-modelling clauses are Adopted until Packet 6 brings a DbContext.
03 Frontend Coding Adopted ESLint and TypeScript strict mode are configured, but apps/web is a scaffold with no components and no tests. First real code: Phase 02d.
04 API Design Adopted No endpoint exists. Problem Details, cursor pagination, idempotency and ETag land in Packet 4.
05 Database Adopted No DbContext and no migration exist. The canonical RLS template it now owns is applied by Packet 6's first migration.
06 Testing Active Unit, architecture and contract suites run in CI, and the meta-test proves the architecture suite can fail. The integration suite does not: the backend job filters it out (FullyQualifiedName!~LearnStack.Tests.Integration) and its own job is gated on an unset vars.ENABLE_BACKEND_INTEGRATION until Phase 02a Packet 7 lands the first isolation test.
07 Frontend Architecture Adopted Route groups exist as empty layouts; server/client split, tenant context and SDK shape are exercised first in Phase 02d.
08 Localization Adopted tenant_locales and the slug schema land in Packet 6; the i18n runtime in Phase 04.
09 Error Handling Active L1 IExceptionHandler, the exception hierarchy, ProblemDetailsFactory and HttpStatusMap shipped in Packet 3.
10 Observability Active Serilog → OTLP, OpenTelemetry SDK, TenantContextSpanProcessor and the redaction enrichers shipped in Packet 3.
11 Security Adopted No auth, no RLS, no header middleware yet. Tenant isolation lands in Packet 7, authentication in Phase 02b. Its § Tenant Context is nonetheless the binding authority the implementing PR must follow.
12 Infrastructure Active Compose stack, Makefile, CI workflow, pre-commit hooks and secret scanning all live since Phase 01.
13 Documentation Active Governs this corpus; the CI link audit walks changed Markdown.
14 Git Workflow Active Conventional Commits, hooks and required checks are live. The branch-protection settings that contradict this standard are reconciled in Packet 3b.
15 Performance Adopted No budget is measured and no load test exists. Enforcement lands in Phase 11.
16 Accessibility Adopted No user interface to audit. First surfaces render in Phase 02d; automated axe checks in Phase 06.
17 Code Review Active Applied to every pull request merged so far; the zero-tolerance blocker list is in live use.
18 Audit Coverage Adopted AuditLogBehavior is a shell and audit_log does not exist. Lands in Packet 9 under ADR-0033.
19 Permissions Adopted No permission key, policy or role exists. Lands in Phase 03.
20 Infrastructure Stack Adopted ISecretProvider shipped in Packet 3 and DeploymentMode branching is real, but the ports land in Packet 5 and the Dapr / Kafka / APISIX / Vault adapters are demand-gated to Phase 11 per ADR-0035.
21 Architecture Tests Catalogue Active Fourteen tests run in CI; the catalogue's own per-row status column distinguishes those from the registered-but-unimplemented majority.

Eleven Active, eleven Adopted. That split is the honest picture of a platform whose foundation is real and whose domain has not been written yet — and it is far more useful to a reviewer than twenty-two identical labels.

Relationship to ADRs

Document type Purpose
ADR (docs/decisions/) A one-time decision with status, context, decision, consequences. Immutable history.
Standard (docs/standards/) An ongoing rule that the team applies day to day. Editable as the team learns.

When a standard is established, an ADR records the moment of adoption. The ADR then points at the standard for the living detail.

Tooling

Where a standard can be enforced by automation, it must be:

  • Roslyn analyzers / .editorconfig for backend.
  • ESLint / TypeScript strict mode for frontend.
  • Custom architecture tests (NetArchTest / ArchUnitNET) for module-boundary rules.
  • Test conventions enforced by CI.
  • Commit / PR rules enforced by GitHub Actions and CODEOWNERS.

Manual-only rules are flagged in each document.