Back to catalog

atomic-crm-constitution

Use when implementing features in Atomic CRM - enforces Engineering Constitution principles including fail-fast error handling, single source of truth for validation, form state from Zod schemas, and pre-launch velocity over resilience

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
name: atomic-crm-constitution
description: Use when implementing features in Atomic CRM - enforces Engineering Constitution principles including fail-fast error handling, single source of truth for validation, form state from Zod schemas, and pre-launch velocity over resilience
---

# Atomic CRM Engineering Constitution

## Overview

Enforce Atomic CRM's Engineering Constitution principles to prevent over-engineering and maintain codebase velocity. Most critical: **fail fast** (no retry logic/circuit breakers) and **single source of truth** (Zod validation only).

**Core principle:** Pre-launch phase prioritizes velocity over resilience. Simple solutions over clever ones.

## When to Use

Use this skill when:
- Handling errors or adding resilience
- Adding validation or data transforms
- Creating forms with default values
- Defining TypeScript types
- Editing existing files
- Creating database migrations

Do NOT use for:
- Reading documentation
- Analyzing existing code
- Non-implementation tasks

## Pre-Implementation Checklist

**Before writing code, verify:**

- [ ] Read `.claude/engineering-constitution.md` if unsure about any principle
- [ ] Error handling: Am I adding retry logic? (NO - fail fast)
- [ ] Validation: Am I validating outside Zod schemas? (NO - API boundary only)
- [ ] Form defaults: Am I hardcoding in component? (NO - use `zodSchema.partial().parse({})`)
- [ ] TypeScript: Using `interface` for objects, `type` for unions?
- [ ] Editing file: Am I fixing nearby issues? (YES - Boy Scout Rule)

## Critical Rules

### 1. NO OVER-ENGINEERING (Most Violated)

**Rule:** No circuit breakers, retry logic, or graceful fallbacks. Fail fast.

**Context:** Pre-launch phase = velocity over resilience. We want **loud failures**, not silent degradation.

**❌ FORBIDDEN PATTERNS:**
```typescript
// ❌ Circuit breaker
class CircuitBreaker {
  state: 'OPEN' | 'CLOSED' | 'HALF-OPEN'
}

// ❌ Retry logic with exponential backoff
for (let i = 0; i < MAX_RETRIES; i++) {
  try {
    return await operation()
  } catch (error) {
    await sleep(Math.pow(2, i) * 100)
  }
}

// ❌ Graceful fallbacks
try {
  return await fetchData()
} catch {
  return cachedData // Silent degradation
}

// ❌ Health monitoring
if (failureCount > threshold) {
  activateCircuitBreaker()
}
```

**✅ CORRECT PATTERN:**
```typescript
// ✅ Let it throw - operator sees error immediately
const data = await supabase.from('contacts').select()
// If 429 error occurs, it throws
// Operator investigates and fixes at source
```

**Why Fail Fast:**
- Complex error handling = maintenance burden
- No users yet = no one benefits from resilience
- Loud failures = immediate investigation
- Silent degradation = hidden problems

**Common Rationalizations to REJECT:**
- "This is for production" → We're **pre-launch**, velocity matters more
- "It needs to be resilient" → Resilience = fail loud, not graceful degradation
- "Users will see errors" → **No users yet**, operators need to see errors
- "Industry best practice" → Context matters, pre-launch has different needs

### 2. SINGLE SOURCE OF TRUTH

**Rule:** Zod schemas at API boundary (`src/atomic-crm/validation/`) ONLY. No validation elsewhere.

**❌ WRONG - Multiple Validation Sources:**
```typescript
// ❌ Validation in component
const isValidEmail = (email: string) => /@/.test(email)

// ❌ Validation in utils
function validateContact(data) {
  if (!data.email?.includes('@')) throw new Error()
}

// Now two+ definitions can diverge!
```

**✅ CORRECT - Zod at API Boundary:**
```typescript
// src/atomic-crm/validation/contacts.ts
export const contactSchema = z.object({
  email: z.string().email(), // Single source of truth
})

// Import everywhere:
import { contactSchema } from '@/atomic-crm/validation/contacts'
```

### 3. FORM STATE DERIVED FROM TRUTH

**Rule:** React Hook Form `defaultValues` MUST use `zodSchema.partial().parse({})`.

**❌ WRONG - Hardcoded Defaults:**
```typescript
// ❌ Hardcoded in component
const form = useForm({
  defaultValues: {
    stage: 'new_lead', // Out of sync with schema!
    priority: 'medium',
  }
})

// ❌ Using defaultValue prop
<SelectInput source="stage" defaultValue="new_lead" />
```

**✅ CORRECT - Schema-Derived Defaults:**
```typescript
// 1. Define defaults in Zod schema
export const opportunitySchema = z.object({
  stage: z.string().default('new_lead'),
  priority: z.string().default('medium'),
})

// 2. Extract defaults in component
const schemaDefaults = opportunitySchema.partial().parse({})
const form = useForm({
  defaultValues: {
    ...schemaDefaults,
    owner_id: identity.id, // Runtime values merged
  }
})

// 3. NO defaultValue props on inputs
<SelectInput source="stage" /> // Uses form default
```

**Why:** Prevents drift between validation and UI.

### 4. BOY SCOUT RULE

**Rule:** Fix inconsistencies when editing files. Leave code better than you found it.

**Examples:**
- See unused import? Delete it
- See inconsistent spacing? Fix it
- See missing type? Add it
- See hardcoded value? Extract to constant

**Scope:** Only fix issues in files you're editing. Don't go on refactoring sprees.

### 5. TYPESCRIPT CONVENTIONS

**Rule:** `interface` for objects/classes, `type` for unions/intersections.

```typescript
// ✅ Interfaces for object shapes
interface Contact {
  id: string
  first_name: string
}

// ✅ Types for unions
type Status = 'active' | 'inactive'

// ✅ Types for intersections
type ContactWithMeta = Contact & { created_at: string }
```

### 6. FORMS - USE REACT ADMIN COMPONENTS

**Rule:** Always use admin layer (`src/components/admin/`) for forms.

```typescript
// ✅ React Admin components
import { TextInput, SelectInput } from 'react-admin'

// ❌ Raw HTML
<input type="text" />
```

### 7. COLORS - SEMANTIC VARIABLES ONLY

**Rule:** Use semantic CSS variables, never hex codes or direct OKLCH.

```css
/* ✅ Semantic tokens */
color: var(--primary);
background: var(--brand-700);

/* ❌ Hex codes */
color: #7CB342;

/* ❌ Direct OKLCH */
color: oklch(65% 0.15 125);
```

**Note:** See `atomic-crm-ui-design` skill for complete color system guidance.

### 8. MIGRATIONS - TIMESTAMP FORMAT

**Rule:** Use Supabase CLI to generate correctly timestamped migrations.

```bash
# ✅ Correct
npx supabase migration new add_contact_tags
# Generates: 20250126143000_add_contact_tags.sql

# ❌ Don't manually create
# 001_add_contact_tags.sql
```

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| "Add retry logic for production" | NO. Fail fast. Pre-launch = velocity over resilience. |
| "Circuit breaker for resilience" | NO. Let errors throw. Investigate and fix at source. |
| Validation in component/utils | Move to Zod schema in `src/atomic-crm/validation/` |
| Hardcoded form defaults | Use `zodSchema.partial().parse({})` |
| `type` for object shapes | Use `interface` for objects |
| Raw `<input>` elements | Use React Admin's `<TextInput>` |
| Leaving unused imports | Fix when editing file (Boy Scout Rule) |

## Implementation Workflow

**1. Check Context**
- Pre-launch = velocity over resilience
- Fail fast over graceful degradation
- Simple over clever

**2. Verify Patterns**
- Error handling: Let it throw
- Validation: Zod at API boundary only
- Forms: Defaults from schema
- Types: `interface` for objects

**3. Boy Scout Rule**
- Fix issues in files you edit
- Don't go on tangential refactors

**4. Commit**
- Verify no retry/circuit breaker code
- Verify no validation outside Zod
- Verify form defaults from schema

## Red Flags - STOP and Review

If you find yourself:
- Writing retry logic → Delete it, let errors throw
- Adding circuit breaker → Delete it, fail fast
- Creating "resilient" error handling → Pre-launch doesn't need it
- Validating outside Zod schemas → Move to API boundary
- Hardcoding form defaults → Use schema.partial().parse({})
- Using `<input>` directly → Use React Admin components
- Ignoring nearby issues → Fix them (Boy Scout Rule)

**All of these mean:** Review Engineering Constitution before proceeding.

## Real-World Impact

**Following Constitution:**
- Fast feature velocity (no over-engineering)
- Loud failures = quick fixes
- Consistent validation (single source)
- No drift between UI and validation
- Clean codebase (Boy Scout Rule)

**Violating Constitution:**
- 3,000+ lines of retry/circuit breaker code
- Hidden failures (silent degradation)
- Validation drift (multiple sources)
- Form defaults out of sync
- Technical debt accumulation

## Quick Reference Cards

### Error Handling

| Situation | DO | DON'T |
|-----------|-----|-------|
| Database error | Let it throw | Retry logic |
| Bulk operations | `Promise.allSettled()` | `Promise.all()` |
| Validation error | Format for React Admin | Silent failure |
| User notification | Show specific message | Generic "Error" |

### Validation

| Situation | DO | DON'T |
|-----------|-----|-------|
| Where to validate | `src/atomic-crm/validation/` | Component/utils |
| Business defaults | `.default()` in Zod | Hardcode in component |
| Type inference | `z.infer<typeof schema>` | Manual type definition |
| Error format | `{ message, errors: {} }` | Throw raw Zod error |

### Form State

| Situation | DO | DON'T |
|-----------|-----|-------|
| Form defaults | `schema.partial().parse({})` | Hardcode in component |
| Array defaults | Sub-schema with `.default()` | `defaultValue` prop |
| JSONB arrays | `ArrayInput` + `SimpleFormIterator` | Manual array state |
| Submit transform | `transform` prop on CreateBase | Transform in component |

### Database

| Situation | DO | DON'T |
|-----------|-----|-------|
| New table | GRANT + RLS | RLS only |
| Role check | Helper function (`is_admin()`) | Inline check |
| Enum values | Add only (can't remove) | Try to remove |
| Migrations | `npx supabase migration new` | Manual numbering |

## Decision Tree: When This Skill Triggers

```
Starting implementation task?
│
├─ Handling errors?
│  └─ Use error-handling.md
│     - Fail fast (no retry)
│     - Promise.allSettled for bulk
│     - Structured logging
│
├─ Adding validation?
│  └─ Use validation-patterns.md
│     - Zod at API boundary only
│     - Sub-schemas for arrays
│     - Error formatting
│
├─ Creating forms?
│  └─ Use form-state-management.md
│     - Defaults from schema
│     - ArrayInput patterns
│     - Transform prop
│
├─ Database changes?
│  └─ Use database-patterns.md
│     - GRANT + RLS
│     - Helper functions
│     - Migration format
│
├─ Security concerns?
│  └─ Use security-patterns.md
│     - CSV validation
│     - RLS policies
│     - XSS prevention
│
├─ Writing tests?
│  └─ Use testing-patterns.md
│     - Unit for logic
│     - E2E for journeys
│     - 70% coverage
│
└─ Unsure what to do?
   └─ Use anti-patterns.md
      - Learn from mistakes
      - Avoid common errors
```

## Resource Files

Comprehensive patterns with real code examples from Atomic CRM:

### Core Patterns
- [error-handling.md](resources/error-handling.md) - Fail-fast patterns, Promise.allSettled, error logging
- [validation-patterns.md](resources/validation-patterns.md) - Zod schemas, single source of truth, error formatting
- [form-state-management.md](resources/form-state-management.md) - Schema-driven forms, ArrayInput, defaults
- [database-patterns.md](resources/database-patterns.md) - GRANT + RLS, migrations, helper functions

### Security & Testing
- [security-patterns.md](resources/security-patterns.md) - CSV validation, formula injection, RLS policies
- [testing-patterns.md](resources/testing-patterns.md) - Unit tests, E2E tests, coverage requirements

### Anti-Patterns
- [anti-patterns.md](resources/anti-patterns.md) - Common mistakes and how to avoid them

## Constitution Principles Summary

1. **NO OVER-ENGINEERING** - Fail fast, no retry/circuit breakers
2. **SINGLE SOURCE OF TRUTH** - Zod validation at API boundary only
3. **BOY SCOUT RULE** - Fix issues in files you edit
4. **VALIDATION** - API boundary only (`src/atomic-crm/validation/`)
5. **FORM STATE** - Derived from Zod schema (`.partial().parse({})`)
6. **TYPESCRIPT** - `interface` for objects, `type` for unions
7. **FORMS** - React Admin components only
8. **COLORS** - Semantic CSS variables only
9. **MIGRATIONS** - Timestamp format via Supabase CLI

**Full details:** `docs/claude/engineering-constitution.md`

**Cross-Reference:** See `atomic-crm-ui-design` skill for UI design patterns (colors, spacing, accessibility)