Files
crewli/dev-docs/BACKLOG.md

22 KiB

Crewli — Product Backlog

Gedocumenteerde wensen en features die bewust zijn uitgesteld. Bijgewerkt: April 2026

Gebruik: Voeg nieuwe items toe als ze tijdens development ontstaan. Geef elk item een prioriteit en fase zodra je het gaat oppakken.


Fase 3 — Geplande features

ARCH-01 — Recurrence / Terugkerende events

Aanleiding: Schaatsbaan use case — 8 weken, elke za+zo openingsdagen. Wat: Organisator definieert één template sub-event met RRULE. Platform genereert automatisch alle instanties. Details:

  • RRULE formaat (RFC 5545): FREQ=WEEKLY;BYDAY=SA,SU;UNTIL=20270126
  • events.recurrence_rule (string nullable) — al gereserveerd in schema
  • events.recurrence_exceptions (JSON) — cancelled + modified dates
  • UI: "Genereer openingsdagen" wizard
  • Aanpassen van één instantie raakt template niet
  • "Alleen deze dag" / "Alle volgende dagen" / "Alle dagen" (Google Calendar patroon) Schema: Kolommen al aanwezig in v1.7. Alleen generator-logica ontbreekt.

ARCH-02 — Min/max shifts per vrijwilliger

Aanleiding: Zonder limiet claimen enthousiaste vrijwilligers 8+ shifts (48 uur in één weekend), resulterend in burn-out en no-shows op latere shifts. Wat: Per event/festival instelbaar minimum en maximum aantal shifts dat een vrijwilliger kan claimen. Details:

  • events.min_shifts_per_volunteer (int nullable)
  • events.max_shifts_per_volunteer (int nullable)
  • ShiftAssignmentService checkt limiet bij claim/assign
  • Portal toont voortgang: "Je hebt 2 van minimaal 4 shifts geclaimd"
  • Bij bereiken maximum: verdere claims geblokkeerd met melding Prioriteit: Laag — Nice-to-have. Geen prioriteit op dit moment. Afhankelijk van: Shift claiming flow

ARCH-03 — Sectie templates / kopiëren van vorig event

Aanleiding: Organisatoren die elk jaar dezelfde secties en shifts opzetten. Wat: "Kopieer secties van vorig festival" functie in de UI. Kopieert festival_sections + shifts structuur (zonder toewijzingen). Details:

  • UI: dropdown "Kopieer structuur van..." bij aanmaken festival
  • Optie: kopieer alleen secties / secties + shifts / alles
  • Tijden worden proportioneel aangepast aan nieuwe datums Prioriteit: Hoog — bespaart veel handmatig werk bij terugkerende festivals

ARCH-04 — Cross-festival conflictdetectie

Aanleiding: Vrijwilliger die bij twee festivals van dezelfde organisatie op dezelfde dag ingepland staat. Wat: Waarschuwing (geen blokkade) als iemand al actief is op een ander festival van dezelfde organisatie op dezelfde datum. Details:

  • Soft check — waarschuwing tonen, niet blokkeren
  • Relevant bij organisaties met meerdere festivals tegelijk
  • Query: shift_assignments cross-festival op person_id + datum

ARCH-05 — Shift fairness / prioriteitswachtrij

Aanleiding: Populaire shifts worden direct volgeboekt door snelle vrijwilligers. Wat: Optionele wachtrij-modus waarbij het systeem eerlijk verdeelt op basis van: reliability score, aantal uren al ingepland, aanmeldvolgorde. Details:

  • shifts.assignment_mode (enum: first_come | fair_queue | manual)
  • Fair queue: systeem wijst toe op basis van algoritme
  • Organisator keurt resultaat goed voor publicatie Prioriteit: Middel — nice-to-have voor grote festivals

ARCH-06 — Locatie-gebaseerd shift-overzicht

Cross sub-event filter op location_id. Toont alle shifts op een fysieke locatie ongeacht programmaonderdeel. Schema: locations tabel en shifts.location_id bestaan al. Prioriteit: Laag


ARCH-07 — Accreditatie-templates per sectie/dag combinatie

MUST-HAVE bij accreditatie build. Templates worden primaire toewijzingsmethode. Per crowd_type + sectie + dag → automatisch voorgestelde accreditatie-items. Handmatige per-persoon toewijzing is de uitzondering, niet de norm. Schema: Nieuwe tabel accreditation_templates nodig. Prioriteit: Hoog — direct meebouwen bij accreditatie-module


Fase 3 — Communicatie & Notificaties

COMM-01 — Real-time WebSocket notificaties

Aanleiding: Differentiator — geen van de concurrenten heeft dit. Wat: Push notificaties via Laravel Echo + Soketi voor:

  • Nieuwe vrijwilliger aanmelding
  • Shift geclaimd
  • Uitnodiging geaccepteerd
  • Shift niet gevuld (waarschuwing)
  • No-show alert op show-dag Tech: Laravel Echo + Soketi (zelf-gehoste WebSocket server) Frontend: Notificatie bell in topbar activeren

COMM-02 — Topbar volledig activeren

Aanleiding: Vuexy topbar staat er maar is niet aangesloten op Crewli. Wat:

  • Zoekbalk (CTRL+K) aansluiten op Crewli-entiteiten (personen, events, secties zoeken)
  • Notificatie bell koppelen aan COMM-01
  • App switcher: Organizer / Portal wisselen (admin SPA retired; platform admin in /platform/*)
  • User avatar: gekoppeld aan ingelogde gebruiker (deels al gedaan) Prioriteit: Middel — werkt zonder maar verbetert UX significant

COMM-03 — Globale zoekfunctie (cmd+K)

Aanleiding: Differentiator — cross-entiteit zoeken. Wat: Modal zoekbalk die zoekt over: personen, events, artiesten, secties, shifts Tech: Meilisearch of database full-text search Prioriteit: Laag — Fase 4


COMM-04 — SMS + WhatsApp campagnes via Zender

Aanleiding: WeezCrew heeft dit als sterk punt. Wat: Bulk communicatie via Zender (zelf-gehoste SMS/WhatsApp gateway)

  • Normal urgency → email
  • Urgent → WhatsApp
  • Emergency → SMS + WhatsApp parallel Tech: ZenderService (al gedocumenteerd in dev guide) Afhankelijk van: Communicatie module backend

Fase 3 — Show Day & Operationeel

OPS-01 — Mission Control

Aanleiding: In2Event's sterkste feature. Wat: Real-time operationele hub op show-dag:

  • Live check-in overzicht per sectie
  • Artiest handling (aankomst, soundcheck, performance status)
  • No-show alerts met automatische opvolging
  • Inventaris uitgifte (portofoons, hesjes) Prioriteit: Hoog voor show-dag gebruik

OPS-02 — No-show automatisering

Aanleiding: 30-minuten alert voor niet-ingecheckte vrijwilligers. Wat: Automatische WhatsApp/SMS via Zender als vrijwilliger niet is ingecheckt 30 min na shift-starttijd. Schema: show_day_absence_alerts al aanwezig Afhankelijk van: COMM-04 (Zender), OPS-01 (Mission Control)


OPS-03 — Allocatiesheet PDF generator

Aanleiding: WeezCrew heeft branded PDF per crew. Wat: Gepersonaliseerde PDF per vrijwilliger/crew: taakbeschrijving, tijden, locatie, QR-code voor check-in. Tech: DomPDF (al geïnstalleerd) Prioriteit: Middel


OPS-04 — Scanner infrastructuur

Aanleiding: QR check-in op locatie. Wat: Scanstations configureren, koppelen aan hardware. scanners tabel al aanwezig in schema Prioriteit: Laag — Fase 4


Fase 3 — Vrijwilligers & Portal

VOL-01 — apps/portal/ vrijwilliger self-service

Aanleiding: Vrijwilligers moeten zichzelf kunnen aanmelden en shifts claimen zonder toegang tot de Organizer app. Wat:

  • Publiek registratieformulier (multi-step)
  • Login portal voor vrijwilligers
  • Beschikbaarheid opgeven (time slots kiezen)
  • My Shifts overzicht
  • Shift claimen met conflictdetectie
  • "Ik kan toch niet komen" workflow Afhankelijk van: Sections + Shifts backend (al klaar )

VOL-02 — Vrijwilliger paspoort + reliability score

Aanleiding: Platform-breed profiel dat accumuleert over jaren. Wat:

  • Festival-paspoort: visuele tijdlijn van deelgenomen festivals
  • Reliability score (0.0-5.0): berekend via scheduled job
  • Coordinator-beoordeling per festival (intern, nooit zichtbaar)
  • "Would reinvite" indicator bij heruitnodiging Schema: volunteer_profiles, volunteer_festival_history al aanwezig

VOL-03 — Post-festival evaluatie + retrospectief

Aanleiding: Automatische feedback na het festival. Wat:

  • 24u na laatste shift: evaluatiemail naar vrijwilligers
  • Max 5 vragen (beleving, shift kwaliteit, terugkomen?)
  • Gegenereerd retrospectief rapport per festival
  • Coordinator-beoordeling parallel (intern) Schema: post_festival_evaluations, festival_retrospectives al aanwezig

VOL-04 — Shift swap workflow (portal)

Aanleiding: Vrijwilliger wil shift ruilen met collega. Wat:

  • Open swap: iedereen mag reageren
  • Persoonlijke swap: specifieke collega vragen
  • Na akkoord beide: coordinator bevestigt (of auto-approve)
  • Wachtlijst: bij uitval automatisch aanschrijven Schema: shift_swap_requests, shift_absences, shift_waitlist al aanwezig

Fase 3 — Artiesten & Advancing

ART-01 — Artist advancing portal (apps/portal/)

Aanleiding: Crescat's sterkste feature. Wat:

  • Sectie-gebaseerd advance portal via gesignde URL
  • Per sectie onafhankelijk submitbaar (Guest List, Contacts, Production)
  • Milestone pipeline: Offer In → Advance Received
  • Per-artiest zichtbaarheidscontrole van advance secties
  • Submission diff tracking (created/updated/untouched/deleted) Schema: advance_sections, advance_submissions al aanwezig

ART-02 — Timetable (stage + drag-drop)

Aanleiding: FullCalendar timeline view voor podia-planning. Wat:

  • Timeline view per podium
  • Drag-and-drop performances
  • B2B detectie (twee artiesten op zelfde podium zelfde tijd) Tech: FullCalendar (al in stack )

Fase 3 — Formulieren & Leveranciers

FORM-01 — Formulierbouwer

Aanleiding: WeezCrew heeft een krachtige drag-sorteerbare builder. Wat:

  • Drag-sorteerbaar, conditionele logica
  • Live preview
  • Iframe embed voor externe websites
  • Configureerbare velden per crowd type Schema: public_forms al aanwezig

FORM-02 — TAG_PICKER → user_organisation_tags sync rebuild Done in S2b (2026-04-17)

Aanleiding: TagSyncService verwijderd in S2a Form Builder legacy purge. Semantiek (TAG_PICKER-antwoorden syncen naar user_organisation_tags bij registratie-goedkeuring) blijft valide. Wat: Herbouwen als listener op FormSubmissionSubmitted tegen de nieuwe FormValue + TAG_PICKER field_type. Integreren via PersonIdentityService::confirmMatch zonder directe service-injection in PersonController. Eerdere call-sites (nu verwijderd): PersonController::approve(), PersonIdentityService::syncRegistrationTags(). Landed artefacts:

  • App\Services\FormBuilder\FormTagSyncService::rebuildForPerson — idempotent union-of-TAG_PICKER-values rebuild, only mutates source=self_reported rows, no-op when person.user_id IS NULL.
  • App\Listeners\FormBuilder\SyncTagPickerSelectionsOnSubmit — ShouldQueue listener on FormSubmissionSubmitted, filters to event_registration purpose with subject_type=person + at least one TAG_PICKER value. Logs + swallows errors so sibling listeners (§31.1/§31.3/§31.8) keep running.
  • App\Services\PersonIdentityService::confirmMatch — calls FormTagSyncService::rebuildForPerson after setting person.user_id (deferred-sync path for person who submitted before the user account existed).
  • Contract frozen in ARCH-FORM-BUILDER.md §31.10 (authoritative block) and covered by tests/Feature/FormBuilder/Integration/TagPickerSyncListenerTest.

Deferred integration tests (move under FORM-03 if needed): GdprDeleteCascadeTest, EmailNotificationFlowTest, CodeOfConductGatingTest, SupplierIntakeFlowTest, CrowdListAutoAddTest (§31.9). Only §31.10 ships with S2b; other contracts wait until their feature arrives.


FORM-04 — grace_days configurable on public_token rotation

Aanleiding: S2c §10.4 opgeleverd met een hardgecodeerd 7-daagse grace window in PublicFormTokenResolver. rotatePublicToken endpoint accepteert wel een grace_days request param maar schrijft die nergens naartoe; form_schemas heeft geen grace_days kolom. Wat:

  • Kolom form_schemas.public_token_grace_days (unsignedSmallInteger nullable, default null).
  • rotatePublicToken service persisteert de ontvangen grace_days value (fallback: config default).
  • PublicFormTokenResolver::GRACE_DAYS leest uit form_schemas.public_token_grace_days ?? config('form_builder.public_token.default_grace_days', 7).
  • Test: rotatie met grace_days=3 levert 410 na 4 dagen. Prioriteit: Laag — operationele tuning, niet frontend-blocking.

DOC-01 — Scramble / OpenAPI generator voor API.md

Aanleiding: dev-docs/API.md wordt met de hand bijgehouden per sprint — bij snelle iteratie landt hij altijd een slag achter de code. Scramble (of equivalent) genereert OpenAPI uit FormRequest + Resource introspectie zonder annotaties. Wat: Scramble installeren, publieke form endpoints een dedicated public tag geven, CI-hook die de generated spec vergelijkt met een checked-in dev-docs/api.openapi.yaml, README link naar de live viewer. Prioriteit: Middel — verlaagt docs-drift substantieel; past in een "developer-experience" sprint.


FORM-05 — Smart identity-match on public submission values

Public form submissions (subject_type=null) currently always get identity_match_status='pending' because the listener needs a Person to match against and public submissions don't create one yet.

Improve: when a public event_registration submission arrives, extract email + first_name + last_name from the submission values (via the schema's binding config) and call a new PersonIdentityService method: detectMatchesByValues(array $values, string $organisationId): MatchResult

Set identity_match_status to matched / pending / none based on actual lookup. This gives the portal-form UX a meaningful signal instead of a constant pending.

Priority: Medium. Can bundle with organizer person_identity_matches UI (which is also still a frontend gap).


SUP-01 — Leveranciersportal + productieverzoeken

Aanleiding: Leveranciers moeten productie-informatie kunnen indienen. Wat:

  • Token-gebaseerde portal toegang (geen account nodig)
  • Productieverzoek indienen (mensen, tech, stroom, voertuigen)
  • Crowd list indienen voor hun crew Schema: production_requests, material_requests al aanwezig

Fase 4 — Differentiators

DIFF-01 — Cross-event crew pool + reliability score

Aanleiding: Vrijwilligers hergebruiken over events van dezelfde organisatie. Wat: Eén klik heruitnodiging op basis van vorig jaar. Reliability score zichtbaar naast naam in de lijst.


DIFF-02 — Crew PWA (mobiel)

Aanleiding: On-site zelfservice voor crew op hun telefoon. Wat: Progressive Web App voor: shifts bekijken, briefing lezen, clock-in, push notificaties.


DIFF-03 — Publieke REST API + webhooks

Aanleiding: Enterprise integraties. Wat: Gedocumenteerde publieke API + webhook systeem voor third-party integraties (ticketing, HR, etc.)


DIFF-04 — CO2 / Duurzaamheidsrapportage

Aanleiding: Toenemende focus op duurzame events. Wat: Emissieberekeningen op basis van transport en energieverbruik. Status: Expliciet out of scope voor v1.x


Apps & Platforms

APPS-01 — apps/admin/ volledig bouwen RETIRED

Status: Retired — admin SPA (apps/admin/) is afgeschaft. Super admin functionaliteit is verplaatst naar apps/app/ onder /platform/* routes voor super_admin gebruikers.


APPS-02 — OrganisationSwitcher ingeklapte staat fix

Aanleiding: Flikkering/hover-bug bij ingeklapte sidebar. Wat: Correcte weergave en animatie in ingeklapte staat. Prioriteit: Low — cosmetisch, werkt functioneel wel


Technische schuld

TECH-01 — Bestaande tests bijwerken na festival/event refactor

Aanleiding: Na toevoegen parent_event_id worden bestaande tests mogelijk fragiel door gewijzigde factory-setup. Wat: Alle Feature tests reviewen en bijwerken waar nodig.


TECH-05 — ESLint configuratie herstellen in apps/app/

Aanleiding: npm run lint faalt omdat .eslintrc.cjs niet bestaat en er ook geen flat-config equivalent aanwezig is. Effectief draait de app zonder lint, wat botst met CLAUDE.md's zero-compromise regels. Wat: Juiste flat-config installeren en afstemmen op het huidige Vuexy 9.5 template. Moet in één keer groen draaien. Prioriteit: Middel — tooling-gap.


TECH-02 — scopeForFestival helper op Event model OPGELOST


TECH-03 — DevSeeder uitbreiden met festival-structuur OPGELOST


TECH-04 — EventController.store() redundante ternary OPGELOST


Opgeloste items (april 2026)

De volgende items zijn geïmplementeerd en afgerond (673+ tests):

  • TECH-02: scopeForFestival + scopeWithChildren helper scopes op Event model
  • TECH-03: DevSeeder uitgebreid met festival-structuur (secties, tijdsloten, personen)
  • TECH-04: EventController.store() redundante ternary
  • Auth race condition (CTRL+R fix)
  • Section edit dialog bug
  • Time slot duplicate button
  • Browser autocomplete disabled op dialog form fields
  • Category + icon fields op festival_sections
  • IconPicker component
  • Crowd Types beheer-UI
  • Companies CRUD
  • Person tags backend (person_tags + user_organisation_tags)
  • Event status state machine (dedicated transition endpoint, prerequisites, festival cascade)
  • Event status transition buttons (frontend + backend, state machine, cascade)
  • Festival tab-navigatie (uniform tabs, Programmaonderdelen tab)
  • SectionsShiftsPanel extractie als herbruikbaar component
  • Cross-event section auto-redirect
  • Shift claiming in portal (5 endpoints, 26 tests, ClaimenTab + RoosterTab)
  • Cross-app auth isolation (CookieBearerToken per app, 3 isolatietests)
  • Password reset (beide SPAs, custom notification, app-aware links)
  • Email change with verification (self-service + admin, 24h token expiry)
  • Password change while logged in
  • "Lid toevoegen als deelnemer" shortcut (2 endpoints, 11 tests)
  • Person Identity Matching (detect→suggest→confirm, fuzzy name, DOB tiebreaker)
  • Naam-splitsing first_name + last_name (66 files)
  • Date of birth op persons en users
  • Smart assign dialog (tags, preferences, availability, cascading filters)
  • Soft capacity + approve overbook fix
  • Cancellation source tracking + re-assignment
  • VitePress user documentation (3 core pages)
  • Registration settings (show_in_registration)
  • Premium portal wizard (banner, branding, success page)
  • Global error handling (useNotificationStore + axios 422 interceptor)

Bekende gaps — nog te bouwen

Overzicht van bekende ontbrekende onderdelen die nog niet gebouwd zijn:

Item Status Prioriteit
Person Tags frontend UI Backend compleet, geen organiser UI Hoog
Accreditatie Engine (SCHEMA 3.5.6, ARCH-07 templates) Volgende grote module Hoog
ARCH-03 — Sectie templates / kopiëren van vorig event Niet gestart Hoog
Briefings & Communicatie basis Niet gestart Middel
Artist Advancing portal Niet gestart Middel
UX-01 — Festival setup checklist Niet gestart Middel
UX-03 — Personen per sub-event Niet gestart Middel
ARCH-06 — Locatie-gebaseerd shift-overzicht Niet gestart Laag

Nieuwe backlog items

ARCH-06 — Locatie-gebaseerd shift-overzicht

Cross sub-event filter op location_id. Toont alle shifts op een fysieke locatie ongeacht programmaonderdeel. Prioriteit: Laag


ARCH-07 — Accreditatie-templates per sectie/dag combinatie

MUST-HAVE bij accreditatie build. Templates worden primaire toewijzingsmethode. Per crowd_type + sectie + dag → automatisch voorgestelde accreditatie-items. Prioriteit: Hoog — direct meebouwen bij accreditatie-module


ARCH-08 — Recurrence voor time slots

Herhalingsfunctie: "genereer 5 time slots in één keer" voor opbouwdagen etc. Prioriteit: Middel


ART-03 — Artist profile met cross-event rider defaults

Organisatie-niveau artiest-profiel dat rider-defaults, contacten en interne notities opslaat over events heen. "Importeer van vorig jaar" functie. Prioriteit: Laag


UX-01 — Festival setup checklist / onboarding wizard

Checklist widget op festival dashboard die door de configuratiestappen leidt. Items worden groen als ze zijn afgerond. Prioriteit: Middel


UX-02 — Aandachtsmatrix op event dashboard

Aanleiding: Organisator verliest overzicht bij 200+ vrijwilligers en 30 secties. Kritieke problemen (onderbezette shifts, wachtende goedkeuringen, onopgeloste identity matches) worden pas ontdekt als het te laat is. Wat: Drie metric cards op het event Overzicht-tab:

  • Goedgekeurde personen zonder shift-toewijzing (telling)
  • Wachtende shift-claims (telling)
  • Onopgeloste identiteitsmatches (telling) Elke card is klikbaar en navigeert naar de relevante module. Prioriteit: Hoog — eerste frontend-taak op Overzicht-tab. Data is beschikbaar via bestaande endpoints (aggregate queries).

UX-03 — Personen-tab op sub-event niveau

Gefilterde view: alleen personen met shifts in dit programmaonderdeel. Met link "Bekijk alle personen op festival-niveau". Prioriteit: Middel


COMM-05 — Resend invitation endpoint

Aanleiding: Uitnodigingen kunnen nu alleen ingetrokken worden of verlopen vanzelf. Organisatoren willen een "opnieuw versturen" actie voor gevallen waarin de oorspronkelijke mail in de spamfilter belandde, gemist werd, of het e-mailadres net gecorrigeerd is. Wat:

  • Backend: POST /api/v1/organisations/{org}/invitations/{id}/resend (idempotent: regenereert de mail zonder token of verloopdatum te wijzigen). Zelfde endpoint voor /admin scope.
  • Frontend: "Opnieuw versturen" actie activeren in de sectie openstaande uitnodigingen op /members (useMembers heeft al een useResendInvitation stub-ready). Prioriteit: Middel — user-requested UX-verbetering.

UX-04 — Leveranciers-deadline waarschuwing

Aanleiding: Leveranciers die hun personeelslijst niet tijdig indienen veroorzaken last-minute chaos. De organisator heeft geen zicht op welke externe lijsten nog niet compleet zijn. Wat: Op het event dashboard en in de publiekslijsten-tab:

  • Badge "Nog niet compleet" op externe lijsten waar persons_count < max_persons
  • Optioneel: deadline-datum veld op crowd_lists (nieuw kolom)
  • Waarschuwingsbanner X dagen voor de deadline: "3 leveranciers hebben hun lijst nog niet compleet ingediend" Prioriteit: Middel — meebouwen bij leveranciersportaal (SUP-01)

Laatste update: April 2026 Voeg nieuwe items toe met prefix: ARCH-, COMM-, OPS-, VOL-, ART-, FORM-, SUP-, DIFF-, APPS-, TECH-, UX-