diff --git a/docs/engineering-standards.md b/docs/engineering-standards.md new file mode 100644 index 0000000..7f1ffb0 --- /dev/null +++ b/docs/engineering-standards.md @@ -0,0 +1,40 @@ +# Engineering standards + +## TypeScript (§10) + +Server baseline: `target ES2023`, `module NodeNext`, `moduleResolution NodeNext`, `strict`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`, `noImplicitOverride`, `useUnknownInCatchVariables`, `verbatimModuleSyntax`, `declaration`, `sourceMap`. Admin/Vite may use `moduleResolution: "Bundler"`. ESM-first; no `any` in public SDK contracts; runtime data validated even when TS types exist; public contract types narrow and intentionally versioned. + +## Data access & transactions (§24) + +Kysely exists only in the DB adapter/extension-storage implementation: `PostListSection → ContentQueryService → ContentRepository (interface) → PostgresContentRepository → Kysely/pg`. Mutating commands are transactional (validate → BEGIN create revision / update entry / update publish state → COMMIT → best-effort domain event). + +## Migrations (§25) + +Core migration IDs immutable and ordered. Each extension owns an independent chain in `eppp_extension_migrations`. Startup: connect → advisory migration lock → core migrations → discover/validate manifests → extension migrations → release lock → activate registries → readiness. Never edit a released migration; fix mistakes in a new one; destructive changes require backup/recovery notes; favour expand/contract; failure identifies extension/migration ID; replicas cannot race; PG major upgrades are separate operator procedures. + +## Test strategy (§58) + +- **Unit (Vitest 4.1.10):** content transitions, slug rules, manifest/version validation, theme/preference resolution, settings validation, block schema/migration, navigation validation. +- **Integration (real PostgreSQL 18.6):** repositories, transactions, migrations, advisory lock, sessions, preference persistence, extension migration ledger, queries/indexes. Fastify injection for route-level integration. +- **E2E (Playwright 1.62.1):** bootstrap/login, create draft, draft-not-public, publish, edit/revision, Home composition, navigation, logout/session expiry, theme selection, preference persistence, extension disable safety. Public flows run in Chromium, Firefox, WebKit. +- **Container smoke:** build → compose → ready → bootstrap fixture → publish → fetch Home/article → restart → verify persistence. + +## CI/CD quality gates (§59) + +Every PR: frozen install, formatting/lint, typecheck, unit tests, architecture fitness tests, PostgreSQL integration tests, admin build, server/public build, manifest/schema validation. Main/release additionally: Docker image build, Compose smoke, Playwright critical E2E, migrate-from-previous fixture, restore test, dependency/security scan, SBOM generation. + +## Architecture fitness tests (§57, CI-enforced) + +FIT-001 core imports no concrete extension · FIT-002 no Amber token values in core · FIT-003 unique namespaced extension IDs · FIT-004 unique contribution IDs · FIT-005 manifests validate · FIT-006 default settings validate · FIT-007 old document fixtures render/migrate · FIT-008 disable/re-enable without data loss · FIT-009 invalid/missing theme falls back · FIT-010 browser bundles can't import server/DB packages · FIT-011 UI can't import Kysely/pg · FIT-012 no core hydration bundle · FIT-013 migration IDs immutable/unique · FIT-014 golden tuple passes · FIT-015 no outbound HTTP outside hardened fetch · FIT-016 chart SVG has no literal colour values · FIT-017 embed iframes only allowlisted + CSP matches. + +## Definition of Ready (§44) + +A story enters a sprint only when: outcome, acceptance criteria, owning module, core-vs-extension ownership, data/schema impact, migration requirement, security impact, failure states, UX states, API impact, observability need, test strategy, dependencies are all known. "Add plugin support" is not a ready story. + +## Definition of Done (§45) + +Acceptance criteria pass; dependency rules pass; runtime input validated; unit/integration/E2E tests pass; immutable migrations; failure state implemented/tested; accessibility + responsive verified; security addressed; diagnostics appropriate; schema/API version bumped if needed; older fixtures still work/migrate; docs updated; Docker build succeeds; Compose smoke passes; peer review completed. + +## Non-functional requirements (§66) + +Latency targets are measurement-first (reference hardware agreed in Sprint 7). **Byte budgets are day-one and CI-asserted (v1.1):** public HTML <30 KB compressed; CSS <20 KB compressed; public JS outside opt-in islands = 0 bytes (FIT-012); each island <10 KB compressed; third-party requests on initial load = zero.