Scrum4Me/README.md
Janpeter Visser 7ae8a24372
Sprint: pbi-55 (#156)
* 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>
2026-05-07 21:46:01 +02:00

299 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
![ERD](./docs/assets/erd.svg)
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)