# Crewli — Zero-Compromise Vibe Coding Aandachtspunten Referentiedocument voor het aansturen van AI agents (Claude Code & Cursor). Alle 18 principes zijn verwerkt in de master prompts. Dit document dient als overzicht en review-checklist. --- ## De 18 principes — waar ze landen | # | Principe | Master Prompt CC | Master Prompt Cursor | Sectie | |---|----------|:---:|:---:|--------| | 1 | Architectuur eerst | ✅ Regel 1 | — | Architecture & design | | 2 | Delete > Adapt | ✅ Regel 2 | ✅ Regel 7 | Architecture & design | | 3 | Strict layering | ✅ Regel 3 | ✅ Regel 4, 6 | Architecture & design | | 4 | Contract-first | ✅ Regel 4 | ✅ Regel 2, 3 | Architecture & design | | 5 | Tests als design | ✅ Regel 11, 12 | — | Testing | | 6 | Idempotency & resilience | ✅ Regel 21 | — | Resilience & operations | | 7 | Naming is architecture | ✅ Regel 9 | ✅ Regel 16 | Code quality | | 8 | Security & auth direct goed | ✅ Regel 16, 17 | ✅ Regel 17 | Security & multi-tenancy | | 9 | Performance by design | ✅ Checklist | ✅ (via composable pattern) | Verification | | 10 | Consistency > cleverness | ✅ Regel 5 | ✅ Regel 8 | Architecture & design | | 11 | Observability dag 1 | ✅ Regel 22 | — | Resilience & operations | | 12 | Versioning & backward compat | ✅ Regel 23 | — | Resilience & operations | | 13 | Data model = heilig | ✅ Regel 13, 14, 15 | — | Data & persistence | | 14 | Prompt discipline | ✅ Hele structuur | ✅ Hele structuur | (Meta) | | 15 | Perfectie vs. pragmatiek | ✅ Regel 3 + 5 | ✅ Regel 8 | Architecture & design | | 16 | Zero TODO | ✅ Regel 7 | ✅ Regel 14 | Code quality | | 17 | Single Source of Truth | ✅ Regel 6 | ✅ Regel 9 | Architecture & design | | 18 | Definition of Done | ✅ Checklist | ✅ Regel 19 | Verification | --- ## Projectspecifieke aandachtspunten (bovenop de 18) ### Bestandspaden — correcte referenties | Wat | Correct pad | Fout (oude pad) | |-----|-------------|-----------------| | Schema definitie | `/dev-docs/SCHEMA.md` | `/docs/SCHEMA.md` | | API contract | `/dev-docs/API.md` | `/docs/API.md` | | Design document | `/dev-docs/design-document.md` | `/docs/design-document.md` | | Dev guide | `/dev-docs/dev-guide.md` | `/docs/dev-guide.md` | | User docs (VitePress) | `/docs/` | — | | Workspace rules | `/CLAUDE.md` (root) | — | | Axios instance (app) | `apps/app/src/lib/axios.ts` | `src/utils/api.ts` etc. | ### PHP Enums — verplicht voor alle status/type velden Agents gebruiken graag string literals. Dwing af: ```php // ❌ VERBODEN $assignment->status = 'approved'; Rule::in(['pending_approval', 'approved', 'rejected']) // ✅ VERPLICHT $assignment->status = ShiftAssignmentStatus::APPROVED; Rule::enum(ShiftAssignmentStatus::class) ``` Alle bestaande/verwachte Enums (uit SCHEMA.md): - `BillingStatus` — trial|active|suspended|cancelled - `EventStatus` — draft|published|active|completed|archived - `PersonStatus` — invited|applied|pending|approved|rejected|no_show - `ShiftAssignmentStatus` — pending_approval|approved|rejected|cancelled|completed - `InvitationStatus` — pending|accepted|expired|revoked - `CrowdListType` — internal|external - `BookingStatus` — pending|offer_sent|confirmed|cancelled|declined - `AdvanceSectionStatus` — not_started|in_progress|submitted|approved ### Service Layer — wanneer wel/niet **Gebruik een Service class wanneer:** - Business logic meer is dan "opslaan wat de FormRequest valideert" - Meerdere modellen gewijzigd worden in één actie - Side effects nodig zijn (notifications, activity log, queue jobs) - Dezelfde logica vanuit meerdere controllers aangeroepen kan worden **Voorbeelden in Crewli:** - `ShiftAssignmentService` — assign, claim, approve, reject (status machine + notifications) - `PersonIdentityService` — deduplicatie, user_id matching - `AccreditationService` — toekennen, intrekken, budget checks - `ZenderService` — SMS/WhatsApp via externe API **Geen Service nodig voor:** - Simpele CRUD zonder business logic (locations, crowd_types, accreditation_categories) - Hier volstaat de controller direct ### Spatie Activity Log — verplicht gebruik ```php // In elke Service method die state wijzigt: activity() ->causedBy($user) ->performedOn($shift) ->withProperties([ 'old' => ['status' => $oldStatus->value], 'new' => ['status' => $newStatus->value], ]) ->log('shift.assignment.approved'); ``` ### Multi-tenancy mentale test Bij elke nieuwe controller, voer deze test uit: 1. Maak in je hoofd twee organisaties: Org A en Org B 2. Gebruiker X hoort bij Org A 3. Kan X via de API data van Org B zien? → BUG 4. Kan X via de API data van Org B wijzigen? → CRITICAL BUG 5. Kan X via de API afleiden dat data van Org B bestaat? → SECURITY ISSUE ### Idempotency checklist voor queued jobs Elke Job moet deze vragen beantwoorden: - Wat gebeurt er als deze job 2x draait? → Geen dubbele side effects - Wat als het model intussen verwijderd is? → Graceful exit, geen crash - Wat als de externe API (Zender) een timeout geeft? → Retry met backoff - Wat als de status intussen veranderd is? → Check-before-act --- ## Review checklist — na elke Claude Code / Cursor sessie ### Backend (Claude Code output) - [ ] Geen TODO/FIXME/HACK (`grep -rn "TODO\|FIXME\|HACK" api/app/`) - [ ] Geen UUID v4 (`grep -rn "uuid(" api/database/migrations/`) - [ ] Geen `Model::all()` zonder scope - [ ] Geen business logic in controllers (alleen HTTP + delegate to Service) - [ ] PHP Enums gebruikt (niet string literals) - [ ] Activity log in Service methods - [ ] Tests draaien groen (`php artisan test`) - [ ] Migratie heeft `down()` method - [ ] Policies compleet (geen `return true` placeholders) - [ ] N+1 check: `with()` in index/show actions - [ ] `/dev-docs/API.md` bijgewerkt ### Frontend (Cursor output) - [ ] Geen `any` types (`grep -rn ": any\|as any" apps/*/src/`) - [ ] Geen directe axios imports in components - [ ] Types gedefinieerd in `src/types/` - [ ] Drie states: loading, error, empty - [ ] Zod schema voor formulieren - [ ] Vuetify componenten (geen onnodige custom CSS) - [ ] Mobile responsive op 375px - [ ] `npx tsc --noEmit` groen