From 3a3b66f4abd52bf4656f38af66ebb64dd187c6bd Mon Sep 17 00:00:00 2001 From: Danijel Martinek Date: Fri, 8 May 2026 17:07:24 +0200 Subject: [PATCH] docs(claude): generators + events/jobs conventions --- CLAUDE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index be0f32d..681f006 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,6 +9,8 @@ pnpm build # Build all packages pnpm test # Run all tests pnpm turbo boundaries # Validate workspace dependency graph pnpm turbo gen feature # Scaffold a new feature package (see docs/guides/scaffolding-a-feature.md) +pnpm turbo gen event # Scaffold an event contract (publish) or handler (consume) +pnpm turbo gen job # Scaffold a background job docker compose up -d # Start PostgreSQL ``` @@ -34,6 +36,7 @@ Turborepo + pnpm monorepo organized by vertical features. Each feature (`auth`, - `docs/architecture/vertical-feature-spec.md` — Design spec with rationale and decision log - `docs/guides/scaffolding-a-feature.md` — `turbo gen feature` reference (fast path; prefer this over the manual walkthrough) - `docs/guides/adding-a-feature.md` — End-to-end new feature walkthrough (manual path; for cases the generator's Phase-1 scope doesn't cover) +- `docs/guides/events-and-jobs.md` — publish/consume/schedule cookbook (cross-feature events + background jobs) ## Key Conventions @@ -58,6 +61,9 @@ Turborepo + pnpm monorepo organized by vertical features. Each feature (`auth`, - **PII handling is non-negotiable** — `sendDefaultPii: false` everywhere (R31, CI grep gate); replay default-masks all text/inputs/media (R34, R35, allowlist starts empty); `Sentry.setUser({ id })` only — no email/username (R36); `beforeSend` + `beforeSendTransaction` scrubbers strip emails/passwords/tokens/cookies/auth/IPs (R32, R33) - **Three apps, three Sentry projects** — `WEB_NEXT_SENTRY_DSN`, `CMS_SENTRY_DSN`, `WEB_TANSTACK_SENTRY_DSN`. Browser DSNs use `NEXT_PUBLIC_` (web-next) and `VITE_` (web-tanstack) prefixes - **Instrumentation binding is orthogonal to repo binding** — `bindAll()`'s Rule 0 (DSN → Sentry vs Noop) is independent of `USE_DEV_SEED` / `NODE_ENV`. Run `pnpm dev` with `WEB_NEXT_SENTRY_DSN` set to test the integration locally +- **Cross-feature events go through `IEventBus` (E0)** — In-feature reactions are direct use-case calls, not bus publishes. The bus is for *crossing* feature boundaries (e.g. `auth` → `marketing-pages` welcome email) +- **Event contracts are public; handlers are private (E1)** — Publisher's `events/.event.ts` is exported from the feature root barrel. Consumer's `events/handlers/on--.handler.ts` is never re-exported (ESLint-enforced via `core-eslint/rules/no-handler-reexport`) +- **Jobs are for *deferred* work, not abstraction (J0)** — Synchronous code stays synchronous. A job exists only when something must run off the request path (latency, retries, cron). Feature packages enqueue via `IJobQueue` only — direct `payload.jobs.queue()` is ESLint-blocked outside `core-shared/jobs/` ## MCP Servers