PrismaClientValidationError ('Argument \`not\` must not be null') hit at
runtime when notifications-bridge mounted post-M12 schema change.
Although StringNullableFilter typings allow \`not: null\`, the v7 query
engine rejects it.
Removed the WHERE-side filter in 3 places — null-narrowing already
happens client-side via flatMap / Boolean filter:
- components/notifications/notifications-bridge.tsx
- app/api/realtime/notifications/route.ts
- lib/insights/verify-stats.ts (task_id filter)
Idea-questions / idea-jobs will be routed via separate channels in
T-502 + T-507; for now, story-question + task-job paths simply ignore
NULL rows in their post-fetch mapping.
Tests: 479/479 green; tsc clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- new tables ideas + idea_logs with FKs (User/Product/Pbi cascade rules per plan)
- claude_jobs.task_id nullable; new idea_id FK + kind enum + index
+ check-constraint: exactly_one(task_id, idea_id)
- claude_questions.story_id nullable; new idea_id FK + index
+ check-constraint: exactly_one(story_id, idea_id)
- notify_question_change trigger: handles null story_id; idea_id added to payload
Verified against dev DB: tables created, both check-constraints active
(neither-set insert correctly rejected with errcode 23514),
trigger replaced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- new enums IdeaStatus, ClaudeJobKind, IdeaLogType
- new models Idea (with @@unique([user_id, code]) + pbi_id @unique) and IdeaLog
- User.idea_code_counter Int @default(0) for IDEA-{nnn} code generation
- ClaudeJob.task_id nullable; new idea_id + kind fields + index
- ClaudeQuestion.story_id nullable; new idea_id field + index
- existing call sites narrowed to story-questions / task-jobs (idea-paths come in T-502+)
- includes the M12 plan doc copied from /Users/janpetervisser/.claude/plans
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs/runbooks/v1-smoke-test.md (NIEUW): 11-secties handmatige checklist
voor de v1.0-pre-launch verificatie — auth, mobile UA-redirect, happy-path
flow, mobile shell, edit-flows, demo-policy, rate-limiting steekproef,
realtime, debug-routes 404 in productie, Lighthouse a11y per pagina,
rollback-trigger.
v1-readiness.md: 4 Before-launch items afgevinkt (demo-policy, privacy,
README, CHANGELOG); smoke-test verwijst nu naar de checklist; PWA-test
en v1.0.0-bump zijn de twee resterende handmatige items.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Privacy/PII review-pass van Server Actions, API-routes, debug-paths en
Sentry config:
✅ Sentry sendDefaultPii: false in alle drie configs (server/edge/client)
✅ Geen wachtwoord/email/token in console-logs
✅ Pair-id-logs zijn metadata-only (5-min TTL, geen secret)
⚠️ Vier debug-routes hadden geen auth-guard:
- /api/debug/realtime-stream — rauwe pg_notify-stream zonder filtering
- /api/debug/emit-test-notify — anonieme test-emit op het kanaal
- /debug-env — lekt env-var-metadata (hostnames, lengtes, pooled-flag)
- /debug-realtime — UI op dezelfde rauwe pg_notify-stream
Allemaal gemarkeerd als TIJDELIJK met VERWIJDEREN-comments uit M8.
Voor v1 launch: NODE_ENV-guard die in productie 404 retourneert. Lokaal
dev blijft alles werken voor debugging.
Toekomstige cleanup: kunnen worden verwijderd zodra M8-realtime stabiel
draait in productie en niemand ze meer nodig heeft.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit van alle Server Actions revealed drie mutation-paden zonder
isDemo-check, terwijl de demo-policy zegt "demo-user is read-only":
- toggleTodoAction: demo kon eigen todos done/undone toggelen
- archiveCompletedTodosAction: demo kon todos archiveren (bulk)
- leaveProductAction: demo kon productMembership verlaten
Fix: standaard `if (session.isDemo) return { error: 'Niet beschikbaar in
demo-modus' }` toegevoegd, conform de andere mutation-actions.
Andere claim/unclaim/reassign/updateTaskPlan-actions zijn al gedekt via
requireProductWriter() → requireWriter() → demo-throw — nu code-side
geverifieerd voor de hele actions/-tree.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CHANGELOG.md: Keep-a-Changelog formaat met [Unreleased], [0.9.0]-release,
en compact-historie. Klaar voor v1.0.0 release-notes.
README:
- Test-count 69 → 445 (was outdated)
- Quick-start claim over auto-erd-watch in `npm run dev` corrigeren
(npm run db:erd:watch is optioneel, niet automatisch)
- Env-vars-tabel uitgebreid: CRON_SECRET (productie), Sentry DSN +
source-map vars (optioneel)
- CHANGELOG-link in Documentation-sectie
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lighthouse-audit op /products/[id] flagde drie issues; fix in deze PR:
1. **[aria-*] attributes do not match their roles** — pbi-list.tsx had
aria-selected={isSelected} op role="button". aria-selected is alleen
geldig op tab/option/treeitem etc. Voor toggle-buttons is aria-pressed
de juiste attribute.
2. **Touch targets do not have sufficient size** — drie offenders op het
product-backlog scherm (PBI ✎/× iconen, Story ✎ icoon) hadden
~16-18×18px tap-targets via px-1.5/p-0.5. Lighthouse minimum is 24×24
en WCAG AA streeft 44×44. Fix: inline-flex + min-h-7 min-w-7 (28×28px)
met behoud van het kleine icoon — wel grotere clickable area.
3. Dashboard product-card pencil-icoon kreeg dezelfde fix preventief.
Sprint-backlog heeft hetzelfde patroon op meer plekken; bewust nu niet
aangeraakt om PR scope te beperken tot de ge-auditeerde route. Vervolg-PR
indien sprint-page-audit ook flagt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Statische audit op happy-path-code; 4 categorieën gefixt vóór de Lighthouse-
verificatie die de gebruiker handmatig draait:
1. <main>-landmark op /login en /register (waren <div>); auth-pages krijgen
nu een correcte landmark zodat screen-readers ze kunnen overslaan/nav
2. solo-task-card.tsx: agent-status-pill had role="button" + aria-label maar
GEEN tabIndex en GEEN onKeyDown — keyboard-onbereikbaar. Nu compleet:
tabIndex={0} + Enter/Space-handler
3. Form-label-associaties via htmlFor + id-pairs:
- story-dialog (5): code, title, description, acceptance + priority via labelledby
- task-dialog (3): title, description, implementation_plan
- todo-list PromotePbi/PromoteStory dialogs (6): title, product, pbi, priority
Lighthouse a11y "form-field-multiple-labels" en "label" rules worden
hierdoor groen.
Niet aangeraakt:
- pbi-dialog: htmlFor was al goed gewired
- auth-form: htmlFor was al goed gewired
- Color-contrast: gebruikt MD3-tokens; theoretisch correct (verifieer in
Lighthouse run)
- Heading-hierarchy: nog niet gescand — kan in vervolgronde
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vier config-files volgens Next.js 15+ conventie:
- instrumentation.ts (root) → koppelt server/edge config aan runtime-hook
- instrumentation-client.ts → client-init + onRouterTransitionStart
- sentry.server.config.ts → node-runtime
- sentry.edge.config.ts → edge-runtime (proxy.ts)
next.config.ts gewrapped met withSentryConfig:
- Source-map-upload ALLEEN als SENTRY_AUTH_TOKEN gezet is
- Tunnel /monitoring omzeilt ad-blockers (*.sentry.io)
- Silent buiten CI
SDK is no-op zonder NEXT_PUBLIC_SENTRY_DSN — geen network/overhead in
dev of bij ontbrekende creds. Sample-rates conservatief: errors 100%,
performance 10% in productie / 100% in dev. Geen Replay (privacy-review
nodig + overkill voor MVP). sendDefaultPii uit.
.env.example gedocumenteerd; architectuur-doc bijgewerkt met nieuwe
sleutelbeslissing en file-tree-aanvulling. v1-readiness #1 verschoven
naar 'done', #2 hiermee in flight.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Acceptatiecriteria vroeg om 'flow per scherm' beschrijving in de
Mobile shell sectie. Toegevoegd: stap-voor-stap flow voor Settings,
Backlog en Solo schermen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
De dashboard product-card had al een 'Bewerken'-tekstknop, maar het patroon
in de rest van de app (PBI/story/task in cards) is een hover-zichtbaar
pencil-icoon. Vervangen voor consistentie. Product-detail page-header blijft
tekst — daar staat 'Bewerken' tussen andere text-acties zoals "Sprint actief"
en "Instellingen".
Hergebruikt bestaande ProductDialog en setEditingProduct-state — geen wijziging
aan de dialog of action zelf. Demo-block behouden.
Tests: 4 nieuwe (rendert icoon, opent dialog, demo-disabled, geen icoon op
archived).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Living document onder docs/plans/v1-readiness.md. Vier secties (Now/Next/
Before launch/Later) met concrete actions voor de stap van v0.9.0 → v1.0.0.
Now-kandidaten:
- Edit-icoon op Product (todo cmoq3ox51 — UI-gat)
- Sentry/error-monitoring
- Rate-limiting op alle mutation-endpoints
- Accessibility-audit (Lighthouse a11y >=95)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Release omvat ondermeer PBI-11 (mobile-shell met landscape-lock):
mobile-shell onder /m/* met UA-redirect, route group (mobile)/, gedeelde
auth-guard, gedeelde mobile-fullscreen-dialog-classes, gescheiden
SplitPane cookie-key voor mobile.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- app/(mobile)/m/products/[id]/solo/page.tsx — hergebruikt SoloBoard 1:1 met
desktop. 3-koloms-kanban blijft, NoActiveSprint-fallback ongewijzigd
- T-332 verify-only: TaskDetailDialog regel 383 gebruikt
entityDialogContentClasses → mobile-fullscreen erft automatisch uit ST-1133
- Tests: regressie-vangnet op SoloBoard-hergebruik, requireSession,
NoActiveSprint, en op TaskDetailDialog-className-wiring (geen override)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- app/(mobile)/m/products/[id]/page.tsx — hergebruikt BacklogHydrationWrapper +
BacklogSplitPane + PbiList/StoryPanel/TaskPanel (1:1 zelfde data-fetch als
desktop-page; demo blijft read-only via PbiList/StoryPanel)
- Cookie-key gescheiden: `backlog-${id}-mobile` (beslissing C in
docs/plans/PBI-11-mobile-shell.md) — tab-mode-gebruikers vervuilen de
desktop-split-percentages niet
- closePath en redirect-targets blijven onder /m/products/
- Tab-mode rendert automatisch op <1024px via SplitPane (uit ST-1116)
- Tests: regressie-vangnet op cookie-key, /m/-paden, hergebruik
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bottom-fixed nav-bar met 3 lucide-iconen (ListTree/Activity/Settings).
Verbergt Backlog/Solo-tabs als activeProductId null is.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Toont rotate-overlay in portrait, niets in landscape. Kinderen blijven altijd
in DOM — geen unmount zodat SSE-streams overleven bij rotatie.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vorige planlocatie (~/.claude/plans/twinkly-plotting-wombat.md) was overschreven
met ST-1209-plan; deze doc neemt het over.
Drie aanbevelingen verwerkt na evaluatie tegen huidige codebase:
- A. Gedeelde entityDialogContentClasses muteren (dekt ST-1133 + ST-1138 in één edit)
- B. Eigen route group app/(mobile)/ — nested layout kan parent-NavBar niet onderdrukken
- C. Gescheiden SplitPane cookie-key voor mobile (backlog-3-mobile)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hover-zichtbaar ✎-icoon rechts uitgelijnd op iedere taak-rij; opent dezelfde
edit-dialog als een rij-klik (visuele cue, consistent met PBI/story-rijen).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- PBI-rij in Product Backlog-kolom: ✎-icoon rechts uitgelijnd, opent PbiDialog
(rij is nu div role=button i.p.v. nested-button)
- Story-rij in Sprint Backlog-kolom: ✎-icoon vóór de Trash, opent StoryDialog
- SprintStory + PbiWithStories verrijkt met velden die de dialogen lezen
(description / acceptance_criteria / pbi_id / created_at op story; priority /
status / description op PBI)
- pbi.status via pbiStatusToApi → PbiStatusApi (DB UPPER_SNAKE → API lowercase)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spiegelt het filter-patroon van de Product Backlog-pagina (PbiList) naar de
Sprint-Product-Backlog-kolom: prioriteit + status pills, actieve-filter chips,
localStorage-persistentie. Bestaande collapse-/expand-/alleen-niet-klaar-knoppen
blijven naast de popover staan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bestand stond al in .gitignore (regel 52) maar was eerder gecommit,
waardoor de ignore-regel niet greep. git rm --cached haalt het uit
git's index zonder het lokaal te verwijderen, zodat per-machine
permissies en local-only Claude-settings niet langer per ongeluk in
commits belanden.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§ 4a beschrijft hybrid detail+inline-edit dialogen met dynamische
footer en blur-save: bv. TaskDetailDialog. Maakt expliciet wanneer je
deze variant kiest, welke § 4-eisen blijven gelden en welke vervallen
(geen dirty-guard, geen Cmd+Enter, geen full-record schema).
Profiel docs/specs/dialogs/task-detail.md verwijst nu naar § 4a en
documenteert de layout-keuzes (sticky header, scrollable body,
flex-wrap footer met job-status, plan-textarea max-h-[40vh]).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Story 6 zette entityDialogContentClasses op de buitenkant
(flex flex-col p-0 gap-0 max-h-[85vh]) maar de binnenkant van
TaskDetailContent gebruikte nog losse divs zonder shrink-0/flex-1
overflow-y-auto. Resultaat bij lange implementatieplannen: dialog
groeide tot voorbij de viewport, header zat niet vast en footer-margin
(-mx-4 -mb-4) brak omdat parent nu p-0 heeft.
Fix: header in shrink-0 div met px-6 pt-5 pb-4 + border-b; body in
entityDialogBodyClasses (flex-1 overflow-y-auto px-6 py-6 space-y-6);
footer in entityDialogFooterClasses + flex-wrap voor de variabele
job-status-knoppen. Plan-textarea krijgt max-h-[40vh] zodat een lang
plan niet meteen heel het body-gebied opvult.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aparte 'Entity codes' sectie legt uit dat PBI/Story/Task elk een
verplichte code hebben (max 30 chars, regex), per-product uniek,
stabiel bij re-parenting, met auto-generatie als POST-body de
code weglaat. Voorbeeld response in /next-story en /sprint/tasks
gebruikt nu T-42 i.p.v. ST-356.1 voor task-code.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>