* ST-cmovs79lt: Schema + migratie PushSubscription model Voeg PushSubscription model toe aan prisma/schema.prisma met snake_case-conventie, relation field op User, en bijbehorende migratie (push_subscriptions tabel, FK + index op user_id). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs7e3o: web-push dependency + VAPID env vars feature-gated Voeg web-push + @types/web-push toe aan package.json. Registreer NEXT_PUBLIC_VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT en INTERNAL_PUSH_SECRET als .optional() in lib/env.ts. Documenteer alle vier in .env.example en README. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs7jgr: lib/push-server.ts met sendPushToUser + stale-cleanup Server-only push-lib met VAPID feature-gate, send naar alle subscriptions van een user, en automatische cleanup bij 404/410. Unit tests: success-pad, 410 verwijdert sub, 404 verwijdert sub, andere errors loggen zonder delete. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs7ouz: lib/push-client.ts client-side push helpers + stub actions/push.ts Client-side helpers: isPushSupported, isIOSSafari, isStandalonePWA, urlBase64ToUint8Array, subscribeToPush, unsubscribeFromPush. Stub actions/push.ts zodat imports resolven (implementatie volgt in volgende taak). Unit tests voor urlBase64ToUint8Array. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs7ut4: actions/push.ts subscribeToPushAction + unsubscribeFromPushAction Vervangt stub met volledige implementatie: requireUser via getSession, demo-block, Zod-validatie, upsert met user_id-scoping en user-scoped deleteMany. Tests (8): idempotentie, demo-block, unauthenticated, invalid input. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs80c1: POST /api/internal/push/send met constant-time Bearer check Route: 503 als INTERNAL_PUSH_SECRET uitstaat, 401 bij verkeerd secret (timingSafeEqual), 400 bij invalid JSON, 422 bij Zod-fout, 204 bij succes. push-server.ts: env-import vervangen door process.env om SESSION_SECRET validatie tijdens build te omzeilen. Tests aangepast. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs862j: Admin test-send route + public/sw.js service worker POST /api/internal/push/test-send: requireAdmin check (redirect bij niet-admin), optioneel body met defaults, roept sendPushToUser aan, 204. public/sw.js: push-handler met showNotification, notificationclick met same-origin guard, focus bestaand venster of openWindow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs8jvq: PushToggle component met 3 states + iOS-banner Client component met states loading/unsupported/ios-needs-install/ denied/subscribed/unsubscribed. useEffect detecteert initial status, permission-prompt alleen via user-click. iOS-banner NL, denied-uitleg, subscribe/unsubscribe knoppen met sonner-toasts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs8psg: notifications-sheet + iOS meta-tags in layout notifications-sheet.tsx: PushToggle onderin met sectie 'Notificatie-instellingen' en visuele scheidslijn. app/layout.tsx: appleWebApp.capable, statusBarStyle en mobile-web-app-capable meta-tags toegevoegd via Next.js Metadata API. manifest.json had al display: standalone. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ST-cmovs8vxj: docs/patterns/web-push.md pattern-documentatie Architectuur-diagram, payload-shape, foutcodes, VAPID-config, iOS-quirks, demo-users blokkade, trigger-voorbeelden (server + HTTP) en admin-testroute curl-voorbeeld. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
299 lines
8.8 KiB
Markdown
299 lines
8.8 KiB
Markdown
# Scrum4Me – Agile Project Management Tool
|
||
|
||
## Portfolio samenvatting
|
||
|
||
Scrum4Me is een moderne fullstack webapplicatie voor agile projectmanagement.
|
||
De applicatie is gebouwd als portfolio-project om mijn vaardigheden in moderne softwareontwikkeling, cloud deployment en AI-assisted development te demonstreren.
|
||
|
||
## Doel
|
||
|
||
Veel teams missen overzicht en flexibiliteit in agile workflows.
|
||
Scrum4Me biedt een lichtgewicht, web-based oplossing voor het beheren van sprints, taken en teamprocessen.
|
||
|
||
## Mijn rol
|
||
|
||
- Architectuur en ontwerp
|
||
- Fullstack development (frontend + backend)
|
||
- Database ontwerp
|
||
- Implementatie van authenticatie en API's
|
||
- CI/CD en deployment
|
||
- AI-assisted development workflow
|
||
|
||
## Functionaliteiten
|
||
|
||
- Agile dashboards en product backlogs
|
||
- PBI-, story-, sprint- en taakbeheer
|
||
- Authenticatie en gebruikersbeheer
|
||
- Teamtoegang via eigenaar of gekoppelde Developer
|
||
- API tokens voor externe integraties
|
||
- REST API voor Claude Code workflows
|
||
- Drag-and-drop interactie voor planning
|
||
- Story-activiteitenlog voor plannen, testresultaten en commits
|
||
- Profielfoto, bio en rolbeheer
|
||
|
||
## Technologie stack
|
||
|
||
- Next.js 16 (App Router)
|
||
- React 19
|
||
- TypeScript
|
||
- Prisma ORM
|
||
- PostgreSQL (Neon)
|
||
- iron-session en bcryptjs
|
||
- Zustand
|
||
- dnd-kit
|
||
- Tailwind CSS en shadcn/ui
|
||
- Sharp voor avatarverwerking
|
||
- Vercel Analytics
|
||
- Vercel hosting
|
||
- GitHub Actions / CI-CD
|
||
|
||
## Documentation
|
||
|
||
- [CHANGELOG.md](CHANGELOG.md) — release-historie (Keep a Changelog)
|
||
- [docs/INDEX.md](docs/INDEX.md) — generated index of all docs (front-matter driven)
|
||
- [docs/glossary.md](docs/glossary.md) — domain terms (PBI, Story, MCP-job, etc.)
|
||
- [CLAUDE.md](CLAUDE.md) / [AGENTS.md](AGENTS.md) — agent instructions
|
||
|
||
## Architectuur (kort)
|
||
|
||
- Frontend en backend via Next.js App Router
|
||
- Server Components voor data loading
|
||
- Server Actions voor UI-mutaties
|
||
- Route Handlers voor de externe REST API
|
||
- Database via Prisma + PostgreSQL
|
||
- Auth via versleutelde sessiecookies
|
||
- Producttoegang via eigenaar of `product_members`
|
||
- Deployment via Vercel met Neon als database
|
||
|
||
## Live demo
|
||
|
||
Voeg hier je Vercel link toe.
|
||
|
||
## Screenshots
|
||
|
||
Voeg hier screenshots toe van dashboard, product backlog, sprint planning en instellingen.
|
||
|
||
## Wat ik geleerd heb
|
||
|
||
- Werken met moderne fullstack architectuur in Next.js
|
||
- Databaseontwerp met Prisma en PostgreSQL
|
||
- Server Actions combineren met REST API Route Handlers
|
||
- Beveiliging van cross-user en cross-scope toegang
|
||
- AI-assisted development integreren in een eigen workflow
|
||
- Cloud deployment en verificatie via Vercel
|
||
- Documentatie en agent-instructies verbeteren op basis van code review
|
||
|
||
## Toekomstige verbeteringen
|
||
|
||
- Multi-user samenwerking verder uitbreiden
|
||
- Notificaties
|
||
- Performance optimalisatie
|
||
- Uitbreiding AI-functionaliteit
|
||
- Meer integratietests voor autorisatie en API-flows
|
||
|
||
## Repository
|
||
|
||
https://github.com/madhura68/Scrum4Me
|
||
|
||
---
|
||
|
||
## Technische aanvulling
|
||
|
||
Deze sectie bevat de praktische projectinformatie die nodig is om de app lokaal te draaien, te deployen en veilig door te ontwikkelen.
|
||
|
||
### Lokale setup
|
||
|
||
1. Installeer dependencies:
|
||
|
||
```bash
|
||
npm ci
|
||
```
|
||
|
||
2. Maak lokale environment variabelen:
|
||
|
||
```bash
|
||
cp .env.example .env.local
|
||
```
|
||
|
||
Vul daarna `DATABASE_URL` en `SESSION_SECRET` in. `DIRECT_URL` is optioneel lokaal, maar handig voor migraties in cloudomgevingen.
|
||
|
||
3. Synchroniseer of migreer de database:
|
||
|
||
```bash
|
||
npx prisma db push
|
||
```
|
||
|
||
4. Genereer Prisma Client en de ERD:
|
||
|
||
```bash
|
||
npm run db:erd
|
||
```
|
||
|
||
Deze command voert lokaal `prisma generate` uit. Daardoor worden zowel de Prisma Client als `docs/assets/erd.svg` opnieuw opgebouwd.
|
||
|
||
In CI en deployment wordt bewust alleen de Prisma Client gegenereerd met `prisma generate --generator client`. Het ERD-diagram gebruikt Mermaid/Puppeteer en wordt daarom niet in GitHub Actions of Vercel gegenereerd.
|
||
|
||
5. Seed testdata indien nodig:
|
||
|
||
```bash
|
||
npx prisma db seed
|
||
```
|
||
|
||
6. Start de app:
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
### Testing
|
||
|
||
**Unit tests (Vitest, geen database vereist):**
|
||
|
||
```bash
|
||
npm test
|
||
```
|
||
|
||
Verwacht: alle 445 tests slagen, 0 failures.
|
||
|
||
**API curl-tests (vereist lopende dev server + API token):**
|
||
|
||
```bash
|
||
# Zie scripts/README.md voor setup-instructies
|
||
bash scripts/test-api.sh
|
||
```
|
||
|
||
De curl-tests dekken alle 7 API-endpoints: auth (401), demo-blokkering (403), inputvalidatie (400) en happy paths. Zie `docs/qa/api-test-plan.md` voor het volledige testplan.
|
||
|
||
## Database
|
||
|
||

|
||
|
||
De databasevisualisatie wordt lokaal gegenereerd uit `prisma/schema.prisma` via `prisma-erd-generator`.
|
||
|
||
Handmatige generatie:
|
||
|
||
```bash
|
||
npm run db:erd
|
||
```
|
||
|
||
Optioneel: `npm run db:erd:watch` parallel aan `npm run dev` om bij wijzigingen in `prisma/schema.prisma` `docs/assets/erd.svg` automatisch opnieuw te genereren.
|
||
|
||
Gebruik `npx prisma db push` alleen om het schema naar de database te synchroniseren. Gebruik `npm run db:erd` om lokaal Prisma Client en de ERD te genereren. Gebruik in CI uitsluitend `npx prisma generate --generator client`.
|
||
|
||
De app draait standaard op `http://localhost:3000`.
|
||
|
||
### Scripts
|
||
|
||
```bash
|
||
npm run dev # lokale development server
|
||
npm run lint # ESLint
|
||
npm test # Vitest test suite
|
||
npm run build # productiebuild zoals Vercel die verwacht
|
||
npm run db:erd # Prisma Client + docs/assets/erd.svg genereren
|
||
```
|
||
|
||
### Environment variables
|
||
|
||
Zie [.env.example](.env.example).
|
||
|
||
| Variabele | Verplicht | Doel |
|
||
|---|---:|---|
|
||
| `DATABASE_URL` | Ja | PostgreSQL connection string voor Prisma |
|
||
| `DIRECT_URL` | Nee | Directe Neon connection string voor migraties (Prisma `directUrl`) |
|
||
| `SESSION_SECRET` | Ja | Minimaal 32 tekens; gebruikt door iron-session |
|
||
| `CRON_SECRET` | Productie | Bearer-secret voor `/api/cron/*` routes — required als crons aan staan |
|
||
| `NEXT_PUBLIC_VAPID_PUBLIC_KEY` | Nee | VAPID public key voor Web Push — genereer met `npx web-push generate-vapid-keys` |
|
||
| `VAPID_PRIVATE_KEY` | Nee | VAPID private key voor Web Push |
|
||
| `VAPID_SUBJECT` | Nee | Contact URI voor Web Push (bijv. `mailto:admin@example.com`) |
|
||
| `INTERNAL_PUSH_SECRET` | Nee | Bearer-secret voor `/api/internal/push/*` routes (min 32 tekens) |
|
||
| `NEXT_PUBLIC_SENTRY_DSN` | Nee | Sentry DSN — zonder is de SDK een no-op |
|
||
| `SENTRY_ORG` / `SENTRY_PROJECT` / `SENTRY_AUTH_TOKEN` | Nee | Source-map upload tijdens build |
|
||
| `NODE_ENV` | Nee | Wordt door Node/Vercel gezet |
|
||
|
||
Vercel Analytics gebruikt geen project-specifieke environment variabele in deze app; de component staat in `app/layout.tsx`.
|
||
|
||
## Commit Guidelines
|
||
|
||
We follow a strict commit structure to keep the project maintainable and reviewable.
|
||
|
||
### Rules
|
||
|
||
- 1 commit = 1 logical change
|
||
- Do not mix:
|
||
- features + docs
|
||
- features + config
|
||
- schema + UI
|
||
- Keep commits small and focused
|
||
- Prefer multiple small commits over one large commit
|
||
|
||
### Commit format
|
||
|
||
We use a simplified conventional commit style:
|
||
|
||
- feat: new feature
|
||
- fix: bug fix
|
||
- docs: documentation only
|
||
- chore: config / tooling / cleanup
|
||
- refactor: code improvement without behavior change
|
||
|
||
### Examples
|
||
|
||
Good:
|
||
|
||
```bash
|
||
feat(db): add user profile fields
|
||
feat(api): add avatar upload endpoint
|
||
feat(ui): add profile editor
|
||
docs: document profile feature
|
||
```
|
||
|
||
Bad:
|
||
```bash
|
||
feat: add profile + update docs + fix config
|
||
```
|
||
|
||
### API-overzicht
|
||
|
||
Alle API-endpoints vereisen:
|
||
|
||
```http
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
| Methode | Endpoint | Doel |
|
||
|---|---|---|
|
||
| `GET` | `/api/products` | Actieve producten waarvoor de tokengebruiker eigenaar of teamlid is |
|
||
| `GET` | `/api/products/:id/next-story` | Volgende story uit de actieve sprint |
|
||
| `GET` | `/api/sprints/:id/tasks?limit=10` | Eerste taken van een sprint |
|
||
| `PATCH` | `/api/stories/:id/tasks/reorder` | Taakvolgorde aanpassen; alle IDs moeten bij de story horen |
|
||
| `POST` | `/api/stories/:id/log` | Implementatieplan, testresultaat of commit vastleggen |
|
||
| `PATCH` | `/api/tasks/:id` | Taakstatus of implementatieplan bijwerken |
|
||
| `POST` | `/api/todos` | Todo aanmaken binnen een productcontext |
|
||
|
||
### Security-regels
|
||
|
||
- Server Actions en Route Handlers vertrouwen nooit op losse client-ID's zonder scope-check.
|
||
- Producttoegang loopt via eigenaar of `product_members`.
|
||
- Bulk-mutaties valideren eerst dat alle IDs bij dezelfde toegankelijke parent horen.
|
||
- Denormalized fields zoals `story.product_id` worden afgeleid van de database-parent, niet van form-data.
|
||
- Demo-gebruikers krijgen 403 op schrijfoperaties.
|
||
|
||
### Deployment
|
||
|
||
De productieomgeving is gericht op Vercel + Neon.
|
||
|
||
1. Zet `DATABASE_URL`, eventueel `DIRECT_URL`, en `SESSION_SECRET` in Vercel.
|
||
2. Zorg dat de Neon-database gemigreerd is.
|
||
3. Push naar `main`; Vercel deployt automatisch.
|
||
4. Controleer na deployment:
|
||
- login en dashboard
|
||
- `/api/products` met een API-token
|
||
- avatar-upload
|
||
- Vercel Analytics in het Vercel dashboard
|
||
|
||
### Documentatie
|
||
|
||
- [Functionele specificatie](docs/specs/functional.md)
|
||
- [Technische architectuur](docs/architecture.md)
|
||
- [Backlog](docs/backlog/index.md)
|
||
- [Agent-instructie audit](docs/decisions/agent-instructions-history.md)
|