Commit Graph

158 Commits

Author SHA1 Message Date
0d4afcd072 docs(rfc): amendment A-1 — TEST-INFRA-001 inserted before F2
Trigger: timetable-stabilization sprint (PR #18, #19) surfaced three
diagnostic incidents that the RFC v1.0 sequencing did not anticipate.

Adds TEST-INFRA-001 as prerequisite sprint before F2 (Playwright +
visual regression infrastructure, baselines against prototype HTML).
Extends F5 with dual-tier visual regression scope. Adds R-11 to risk
register, DoD-16 through DoD-20 to Definition of Done.

No changes to F2-F6 internal architecture, Aura preset, FormField API,
Tailwind v4, or bundle size targets.

Effort impact: +5-7 working days. Total now 15-19 days.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-10 13:53:52 +02:00
e2d9797de3 docs(rfc): WS-FRONTEND-PRIMEVUE migration plan v1.0 2026-05-10 02:14:15 +02:00
5d9399b03d docs(audit): WS-FRONTEND-PRIMEVUE F1 codebase inventory
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 01:57:12 +02:00
4acf42429e docs(backlog): sharpen test-infra triggers; add ART-S4-UX-PARITY with seed-list scope
Three trigger upgrades + one new entry, in priority order:

TEST-INFRA-001 — trigger upgraded from "before opening Sessie 5" to
"eerstvolgende sprint na merge van fix/timetable-stabilization", with
explicit dependency: ART-S4-UX-PARITY and all Sessie 5+ work gate on
TEST-INFRA-001 merge. Reden quote captures the three sprint-blok
incidents that proved jsdom-tests do not protect against schema /
filter / UX drift.

TEST-VISUAL-001 — scope expanded to use the prototype HTML at
`./resources/Crewli - Artist  Timetable Management/` as the visual
baseline source (not hand-curated screenshots). Added explicit state
matrix per surface: PerformanceBlock 8 states + B2B + cascade-pulse;
PerformancePopover full detail; AddPerformanceDialog drag-mode +
button-mode; Wachtrij filtered/grouped axes. Trigger remains "tweede
toevoeging na TEST-CONTRACT-001" inside the TEST-INFRA-001 sprint.

TEST-CONTRACT-001 — unchanged. Trigger ("eerste e2e na TEST-INFRA-001
lands") was already correct.

ART-S4-UX-PARITY (NEW) — captures Bert's screenshot-report findings as
a seed list grouped A/B/C/D (component-shape / interaction / logic /
AddPerformanceDialog two-mode). Explicit pointer at the bottom to the
Phase A finalization report for the full 20-item itemisation with
severity ratings. Trigger gates Sessie 5 + all subsequent Artist-domain
frontend work behind ART-S4-UX-PARITY merge.

Spelling consistency: VEE-001 entry "formalized" → "formalised" to
match British-English already used elsewhere in the doc and now
mandated by the new CLAUDE.md "Diagnostic discipline" section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 00:33:16 +02:00
a156fe2a53 docs(backlog): add TEST-INFRA-001, TEST-CONTRACT-001, TEST-VISUAL-001 with sharp triggers; close ART-S4-TESTS
Three new entries that codify the test-architecture roadmap surfaced
during the Session 4 follow-up:

TEST-INFRA-001 — Migrate timetable component+a11y tests to Playwright
Component Testing. **Trigger: before opening the Sessie 5 prompt.**
Sessie 5 builds Engagement Detail (6 tabs) + Portal pages (drag-to-
reorder, file uploads); adding more jsdom-based tests for those
surfaces compounds the migration cost.

TEST-CONTRACT-001 — End-to-end 409 contract test against running Laravel.
Trigger: first e2e flow added after TEST-INFRA-001 lands. Highest
contract-protection value per line of test code.

TEST-VISUAL-001 — Visual regression baselines for PerformanceBlock
states (RFC D21/D22/D25/D26). Trigger: second addition to the
TEST-INFRA-001 sprint.

ART-S4-TESTS marked  Resolved with the audit trail of all 9 commits
that landed the test coverage closure (252 → 385 tests across both PRs).

.claude-sync/ regenerated by the post-commit hook (gitignored;
re-uploaded to Project Knowledge separately).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 03:57:02 +02:00
5c53dcd2e4 chore(forms): remove unused vee-validate; formalize ref+validators+Zod as canonical pattern
Strict-regex sweep of apps/app/src/ confirms zero VeeValidate usage:
no `from 'vee-validate'` imports, no <Field|Form|ErrorMessage>,
no defineRule(), no useForm(). The 15 prior fuzzy matches were
false positives where /useForm/ matched useFormDraft/useFormSteps/
useFormSchemas/useFormFailures.

Changes:
- Remove `vee-validate` and `@vee-validate/zod` from apps/app/package.json
- Regenerate pnpm-lock.yaml (no other deps shifted)
- CLAUDE.md "Forms": replace VeeValidate prescription with the actual
  ref + @core/utils/validators + Zod-payload-schema pattern that the
  codebase already uses everywhere
- VUEXY_COMPONENTS.md: correct the stale "Registration uses VeeValidate"
  claim (the page actually uses useFormDraft + validators); update the
  "Form validation" reference row
- BACKLOG.md: close VEE-001 with the audit trail

All 319 existing tests still pass; vue-tsc clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 03:21:49 +02:00
449581c41e docs(timetable): open TECH-OBSERVER-TEST-CONVERGENCE + ART-ADVANCE-SECTION-FK
Two new BACKLOG entries surfaced during Session 3:

- **TECH-OBSERVER-TEST-CONVERGENCE** — track removal of the
  artist_advance.bootstrap_on_org_create config flag once the five
  FormSchema-counting tests are updated to expect the auto-bootstrapped
  schema. Goal: productiegedrag = testgedrag, geen branching.

- **ART-ADVANCE-SECTION-FK** — replace the name-based bridge between
  advance_sections (engagement-scoped) and form_schema_sections
  (org-scoped) with a real FK. Today's name-match works for default-
  seeded schemas but breaks on UI rename and offers no integrity
  guarantee. Includes migration outline (form_schema_section_id
  nullable FK, ArtistEngagement::created provisioning hook,
  best-effort backfill).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:18:22 +02:00
e26da4fb42 docs(timetable): close ART-OBSERVER-ADVANCE-AGGREGATE; wire event_id through createDraft
§17.3 footnote already accurately describes ArtistResolver::fromPortalToken
(checked at commit cc48011). Wired event_id end-to-end on the cleaner
path: FormSubmissionService::createDraft now accepts event_id via the
\$context bag, and the EngagementPortalController passes it from
\$resolved->eventId. Replaces the prior post-save fallback. Per WS-4
denormalisation requirement.

ART-OBSERVER-ADVANCE-AGGREGATE moved from open to closed — landed in
Session 3 as the AdvanceSectionObserver (commit 1716e09).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:23:43 +02:00
70431fb836 docs(backlog): record EVENT-START-END-TIME for events-table schema upgrade
Surfaced during Session 2 review: events.start_date/end_date (date type)
forces day-boundary semantics in WithinEventBounds. Adding start_time/
end_time would let the Session 4 timetable viewport honour real event
hours and boundary checks reject post-event-close performances.

Cross-cutting schema change — out of scope for Artist Timetable sprint
per Charter §2. Tracked for opportunistic landing alongside a future
events-module sprint OR concrete UX-gap discovery during Session 4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:30:18 +02:00
5c1faf2061 docs(backlog): record AUTH-PERMISSIONS-MIGRATION + ART-DEMOTE-NOTIFICATION
Two new tech-debt entries surfaced by Session 2:

  AUTH-PERMISSIONS-MIGRATION — Crewli is role-based today; RFC-TIMETABLE
  §9 references permission strings. Phase A (2026-05-08) chose Option B
  (role-based, with permission strings as docblock references). The
  eventual cross-cutting migration is tracked here. Trigger:
  customer/charter requirement, not internal preference.

  ART-DEMOTE-NOTIFICATION — Session 2's daily option-expiry command
  writes activity log only; e-mail to the project leader waits for the
  post-Accreditation notification framework.

Also append a Session-2 paragraph to the existing
RFC-TIMETABLE-V0.2-DOC-CLEANUP entry describing the §9 permission-string
mapping decision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:00:34 +02:00
7eec9d148f docs(backlog): record portal_token schema deviation from RFC v0.2 §5.3
Schema reality (varchar(64), accommodating SHA-256 hex digest) diverges
from RFC v0.2 §5.3 ("ULID unique nullable"). Session 1 implementation is
correct; RFC needs amendment in next legitimate cycle. Tracked under
RFC-TIMETABLE-V0.2-PORTAL-TOKEN-SCHEMA-AMEND. Distinct from
RFC-TIMETABLE-V0.2-DOC-CLEANUP (which covers stale cross-references).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:43:19 +02:00
4e5671daa9 docs(backlog): close ARCH-09; open ART-OBSERVER-ADVANCE-AGGREGATE + RFC-TIMETABLE-V0.2-DOC-CLEANUP
ARCH-09 (Artist Eloquent model + migration) closed under
"Opgeloste items (mei 2026)" with summary of what landed in
RFC-TIMETABLE v0.2 Session 1. Removed from Phase 3 status table
and from "Nieuwe backlog items".

Two new tech-debt entries:
- ART-OBSERVER-ADVANCE-AGGREGATE: AdvanceSection lifecycle observer
  to recompute artist_engagements.advancing_*_count, deferred to
  Session 3 when section-level submit lands.
- RFC-TIMETABLE-V0.2-DOC-CLEANUP: capture stale ARCH-PLANNED-MODULES.md
  cross-references in the Approved RFC v0.2 §1 + §15 for next amendment.
  Approved RFCs are not patched ad-hoc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:50:17 +02:00
ad6bf3b44d docs(form-builder): align artist_advance with engagement-scoped sections
§3.2.5: clarify that advance_sections are engagement-scoped (not
artist-scoped). One master artist with two engagements advances each
trajectory independently. Drop the prose section enumeration that
predated the AdvanceSectionType enum and conflated section names
with section types — section type is the enum, name is a free string,
default seeds land in Session 3 with ArtistAdvanceDefault.

§17.3: footnote on the artist_advance row documenting engagement
context resolution — ArtistResolver::fromPortalToken looks up
artist_engagements.portal_token, returns the master Artist as subject,
populates form_submissions.event_id from the engagement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:48:38 +02:00
7e4db29b2b docs(schema): rewrite §3.5.7 Artists & Advancing — RFC v0.2 alignment
Replaces the pre-RFC-v0.2 design (event-scoped artists, milestone bool
flags, artist_riders, itinerary_items) with the master+engagement
split per RFC-TIMETABLE v0.2 §5.3:

- genres (org-scoped vocab, D24)
- artists (master, org-scoped, slug-unique)
- companies.handles_buma column note
- artist_contacts (master-scoped)
- stages, stage_days (event/sub-event pivot)
- artist_engagements (per-event booking — D9, D10)
- performances (engagement-scoped, nullable stage_id, D13/D14)
- advance_sections (engagement-scoped — was artist_id)
- advance_submissions (audit-immutable per RFC §5.4)
- 7 enums under App\Enums\Artist\ documented in their own subsection

artist_riders and itinerary_items removed — RFC v0.2 §5.3 does not
create them; rider data lives in advance-section submissions, and
itineraries are deferred to a future RFC.

TOC anchor unchanged (slug `#357-artists--advancing` still resolves).
ARCH-PLANNED-MODULES.md was assumed to exist by the RFC's pre-amble
and the original session prompt, but does not — §3.5.7 was already in
SCHEMA.md, so the work is an in-place rewrite. Closes ARCH-09.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:47:27 +02:00
296e352e2d docs(rfc-timetable): mark v0.2 as Approved 2026-05-08 17:25:31 +02:00
c9863ee4f8 Add design en information for developing the Artist Management module 2026-05-08 17:01:13 +02:00
a57437a4b7 audit(timetable): complete prototype audit for RFC v0.2
Capture inventory, data model, component architecture, interaction
patterns, pure logic algorithms (with verbatim excerpts), design tokens,
and 20 RFC v0.2 observations from the standalone React prototype at
resources/Crewli - Artist  Timetable Management/.

Read-only audit; no prototype files modified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:04:00 +02:00
5d53ccabae docs(backlog): close TECH-CHANNEL-AUTH-ORG-ADMIN
Mark TECH-CHANNEL-AUTH-ORG-ADMIN as resolved with PR reference,
date, and one-paragraph summary of what was delivered.

Three edits:

1. Open entry block removed from "Technische schuld" section.
2. Closure bullet appended under "Opgeloste items (mei 2026)" — full
   summary of the three-path auth (submitter / super_admin / org_admin),
   pattern source (FormSubmissionActionFailurePolicy::canAccess port),
   the audit-surfaced super_admin bypass bonus, test deltas, and
   sibling FRONTEND-ECHO-IDENTITY-MATCH-SUBSCRIPTION pointer.
3. Stale forward-reference inside FRONTEND-ECHO-IDENTITY-MATCH-SUBSCRIPTION
   updated: "submitter-only voor nu" → "submitter / super_admin /
   org_admin van submission's organisatie — TECH-CHANNEL-AUTH-ORG-ADMIN
   closed mei 2026". Closes the same no-compromises gap as the FORM-05
   stub-status touch-up (PR #12).

Sibling BACKLOG entry FRONTEND-ECHO-IDENTITY-MATCH-SUBSCRIPTION stays
open — that's the frontend portal IdentityMatchBanner work that pairs
with this channel auth extension.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 11:31:08 +02:00
c5682f181f docs(backlog): close no-compromises gaps from WS-6 v1.3-delta review
Three edits closing concessies surfaced in chat review of the closure
docs-PR:

1. FORM-05 'Resterend werk' sub-paragraph: surgical replacement of
   resolveStatus references (method removed in D2, PR #11 23a5696).
   Updated to describe post-D2 reality: gate + invariant +
   handle()-internal status derivation. Ticket stays open (the
   detectMatchesByValues extension is unbuilt).

2. FRONTEND-ECHO-IDENTITY-MATCH-SUBSCRIPTION (NEW): tracks the frontend
   follow-up where the portal IdentityMatchBanner subscribes to the
   submission.{id} channel for live banner updates. Previously
   documented in PR #11 body and RFC §Q1 v1.3 add 2 commentary but
   without an actionable BACKLOG ticket.

3. HARD-DEADLINE-QUERY-TIMEOUT (NEW): tracks the upgrade from soft
   post-call microtime deadline to a hard deadline that can interrupt
   hanging MySQL queries (connection-level timeouts, MAX_EXECUTION_TIME
   hints, or pcntl_alarm). Previously documented as 'soft deadline
   limitation' inline in code comments without an actionable BACKLOG
   ticket.

No spec changes; no code changes. Closes the chat-identified gaps so
WS-6 v1.3-delta closure has zero un-anchored mental TODOs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 10:11:50 +02:00
ce552ec7be docs(backlog): WS-6 v1.3-delta closure entry + FORM-05 stub-status touch-up
Append WS-6-V1.3-DELTA closure bullet under "Opgeloste items (mei 2026)"
summarising D1 (PR #10 c6f4d1b) + D2 (PR #11 23a5696) deliverables and
open follow-ups.

Surgical correction to FORM-05 Stub-status paragraph: pre-D2 description
claimed TriggerPersonIdentityMatchOnFormSubmit writes initial 'pending';
post-D2 that's ApplyBindingsOnFormSubmit's job per RFC §Q1 v1.3 add 1.
The underlying ticket (detectMatchesByValues extension) stays open.

No other BACKLOG entries resolved — D1+D2 implemented RFC §Q3 v1.3
changes that pre-existing tickets didn't anticipate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 08:59:40 +02:00
5ac6b4168d docs(rfc-ws-6): mark v1.3.1 as fully implemented
§1 Status: add Implementation status line citing D1 (PR #10 c6f4d1b)
and D2 (PR #11 23a5696), both 2026-05-08.

§10 Document history: append v1.3-delta closure entry summarising what
D1 and D2 each delivered + what remains as separate operational task
(GlitchTip alert rule configuration in the web UI) and frontend
follow-up (Echo subscription).

No spec changes — purely lifecycle marker update.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 08:57:50 +02:00
7ba01a6dfa docs(runbooks): add form-builder binding failures section
Per RFC-WS-6 §Q3 v1.3 + ARCH-BINDINGS §11.

Nieuwe runbook-sectie §7 (na §6 Audit trail) die de triage-flow
documenteert wanneer GlitchTip een FormBindingApplicatorException
event opbrengt:

- §7.1 failure_response_code classificatie (schema_config_error /
  temporary_error / data_integrity_error / unknown_error) drijft het
  initiële triage-pad
- §7.2 form_schema.has_public_token tag onderscheidt klant-zichtbare
  failures (alert-waardig) van organizer-driven failures (admin-UI only)
- §7.3 retry/dismiss decision-matrix met form-failures:retry artisan
  command + DismissalReasonType enum cases
- §7.4 severe-failure escalatie criteria (>10/uur op één schema = P1)
- §7.5 cross-references naar RFC, ARCH-BINDINGS, en erasure-runbook

Companion van de operationele GlitchTip alert-rule (apart geconfigureerd
in de GlitchTip web UI op monitoring.hausdesign.nl).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 08:57:02 +02:00
94205164ed docs(backlog): TECH-CHANNEL-AUTH-ORG-ADMIN — extend submission.{id} channel auth to org admins
WS-6 v1.3-delta D2 ships the broadcast channel auth callback in
routes/channels.php with submitter-only scope. Org-admin access is
deferred because the codebase has no vetted Spatie Permission helper
for organisation-scoped role checks; guessing the API would risk
incorrect authorisation without test coverage.

Tracking entry under "Technische schuld", referenced from the inline
TODO in routes/channels.php and the v1.3-delta D2 PR description.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 03:00:40 +02:00
b2558791e6 docs(rfc-ws-6): v1.3.1 + ARCH-BINDINGS v1.2 — drift closure pre-D1 implementation
Three code-vs-docs drifts surfaced by the 2026-05-08 v1.3-delta audit.
None changes architecture; all three close the gap between code on main
(845b6e6) and the v1.3 amendment text.

- RFC §3 (Q1): apply_status enumerations updated to four cases (added
  PARTIAL alongside PENDING/COMPLETED/FAILED). PARTIAL is the
  BindingPassResult outcome when the pass committed with mixed
  per-binding outcomes; not a separate runtime path. Long-term direction
  remains BACKLOG PARTIAL-BINDING-SUCCESS.
- ARCH-BINDINGS §5.6: new "PARTIAL handling" subsection clarifying the
  gate treats PARTIAL identically to FAILED until partial-success work
  lands. The gate code itself was already correct (strict equality on
  COMPLETED); this closes the explanatory gap.
- ARCH-BINDINGS §7.1: status-columns table extended with apply_completed_at
  row. Intro line updated. Retry-service asymmetry noted as D2 follow-up
  (FormFailureRetryService::recordFailure currently does not write
  apply_completed_at; D2 fixes this).

RFC v1.3 -> v1.3.1; ARCH-BINDINGS v1.1 -> v1.2.

Refs: dev-docs/RFC-WS-6.md, dev-docs/ARCH-BINDINGS.md, dev-docs/BACKLOG.md (PARTIAL-BINDING-SUCCESS, unchanged)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 01:32:19 +02:00
845b6e6a0e docs(rfc-ws-6): v1.3 amendment — listener queueing, invariant cleanup, failure-UX
Five refinements from the 2026-05-07 architectural review:

- Q1: TriggerPersonIdentityMatchOnFormSubmit moves to queued; sync-chain reduced to ApplyBindings only; queued-listener gating invariant; sync-chain deadline wrapper.

- Q2: Failsafe pad in TriggerPersonIdentityMatch removed in favour of strict invariant + throw; RequiresIdentityKeyBinding unconditional for event_registration; FormSubmissionResource.identity_match=null contract for non-person purposes.

- Q3: Three failure-UX additions (GlitchTip alert, custom exception hierarchy + error_code, BACKLOG entries for partial-success and schema-drift).

Spine unchanged: pre-publish guards, strict service / log-and-swallow listener, two-transaction pattern, single identity-key per target_entity.

Refs: dev-docs/RFC-WS-6.md (now v1.3), dev-docs/ARCH-BINDINGS.md (now v1.1), dev-docs/BACKLOG.md (PARTIAL-BINDING-SUCCESS, FORM-SCHEMA-DRIFT-DETECTION added)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:52:19 +02:00
d4a450d193 docs(backlog): mark WS-7 Observability as closed (mei 2026)
Acceptance criteria 1-14 voldaan; observability volledig operationeel
op monitoring.hausdesign.nl. Implementation criteria 3, 4, 5, 6, 8,
11, 12, 13, 14 via 4 PRs op feat/ws-7-observability; operationele
criteria 1, 2, 7, 9, 10 via deploy-checklist.

Hernoem 'Observability follow-ups (post WS-7)' sectie-header naar
'(post WS-7 closure)' voor accuratesse na PR-3 + PR-4. Closure-entry
geplaatst onderaan 'Opgeloste items (mei 2026)' om chronologische
volgorde (oldest-first) te respecteren — WS-7 op 2026-05-07 volgt
WS-3 PR-C op 2026-05-06 die volgt op WS-TOOLING-001 op 2026-05-05.

Refs: dev-docs/ARCH-OBSERVABILITY.md, dev-docs/runbooks/observability-{triage,erasure}.md
2026-05-07 22:37:15 +02:00
e9da01ffce docs: WS-7 closure — RFC status + SECURITY_AUDIT + BACKLOG + sync config
PR-4 commit 3 — closure-bookkeeping nu de implementation-PRs en de
twee runbooks gemerged zijn.

- RFC-WS-7-OBSERVABILITY.md: nieuwe §9 Implementation status (mei 2026)
  vat samen welke acceptance criteria via PR-1..PR-4 zijn voldaan en
  welke (1, 2, 7, 9, 10) op Bert's deploy-checklist resteren. Pointer
  naar ARCH-OBSERVABILITY.md als levende reference; de RFC blijft
  historisch document.
- SECURITY_AUDIT.md: nieuwe sectie 'WS-7 Observability — finale audit
  (mei 2026)' tussen A13-10 en Positive Findings. Bevat (1) acceptance
  criteria checklist met status per criterium, (2) processing register
  entry voor GlitchTip (controller-not-processor, retention 90 dagen,
  TLS+full-disk-encryption+2FA), (3) zeven security controls die WS-7
  introduceert (PII scrubbing, CSP whitelist, sourcemap upload-only,
  listener registration discipline, runtime portal-context-split,
  multi-tenant tag invariant, impersonation.active binary signal),
  (4) pointer naar runbooks/observability-erasure.md voor Art. 17.
- BACKLOG.md: status-overzicht-tabel boven de OBS-entries. Toegevoegd
  als entry: OBS-2 (early-pipeline log context,  Resolved), OBS-3
  (sentry-context middleware coverage,  Resolved — opgevouwen in
  AuthScopeContextListener), OBS-5 (Crewli render handlers report()
  invariant,  Resolved via 48f2a00 + ExceptionReportingTest), en
  OBS-9 (Active — staging environment GlitchTip CSP whitelist follow-up
  bij staging-introductie). Bestaande OBS-1, 4, 6, 7 ongewijzigd
  (Active); OBS-8 staat al op Resolved sinds dee1401.
- .claude-sync.conf: drie nieuwe doc-paths toegevoegd
  (ARCH-OBSERVABILITY.md, runbooks/observability-triage.md,
  runbooks/observability-erasure.md). Post-commit sync-claude-docs
  hook regenereert SYNC_MANIFEST.md met deze entries.

Closes WS-7 documentation acceptance criteria 8 (ARCH) en 14
(SECURITY_AUDIT). Resterende criteria (1, 2, 7, 9, 10) zijn
deploy-checklist door Bert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:47:12 +02:00
bf89090850 docs: observability triage + erasure runbooks
PR-4 commit 2. Both runbooks live under dev-docs/runbooks/ as the first
entries in that directory.

- observability-triage.md (270 lines): incoming-issue procedure. Tags
  inspectie (actor_scope, release, actor_type, organisation_id,
  impersonation), triage classes (P0–P3), reproductie via request_id
  correlation naar laravel.log, common patterns (validation leakage,
  runaway errors, multi-tenant invariant violations, CSP black-silence),
  resolution + audit trail.
- observability-erasure.md (293 lines): GDPR Art. 17 procedure.
  Trigger voorwaarden (upstream eerst), pre-checks, handmatige
  psql-procedure met counts vóór delete, post-checks, automation
  BACKLOG verwijzing, edge cases (no-events-in-window,
  impersonation-target, queued events, mass-erasure batch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:46:49 +02:00
754222f74d docs: ARCH-OBSERVABILITY.md (WS-8b)
Replaces the WS-6 skeleton with a full post-implementation reference
for the observability stack. Eleven sections covering scope, component
overview, tag taxonomy (replacing RFC §3.6 as source-of-truth), tag
binding architecture, scrubbing semantics, runtime context split, CSP
whitelist, sourcemap upload, GDPR + privacy, maintenance + extension
guidance, plus cross-references.

Form Builder exception classification from the old skeleton §3 is
preserved in §5.4 — concrete answer for which Crewli exception
classes do or do not go to GlitchTip.

Lengte: 730 regels markdown. Closes WS-7 acceptance criterion 8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 19:46:32 +02:00
5c42f27b26 fix: whitelist GlitchTip ingest host in CSP connect-src
PR-3 follow-up. Live smoke surfaced that the @sentry/vue SDK was
running correctly and emitting events, but Crewli's strict
connect-src directive blocked every POST at the browser layer. No
fallback — events evaporated silently with a CSP-violation log in
DevTools console only.

Updated locations (audited the CSP surface; only two locations actually
need the whitelist):

- apps/app/index.html — dev meta CSP, adds http://localhost:8200 to
  connect-src so local dev hits the docker-compose GlitchTip stack.
- deploy/nginx/csp-spa.conf — prod organizer SPA CSP, adds
  https://monitoring.hausdesign.nl to BOTH the report-only and enforce
  add_header lines so a future flip between modes can't silently break
  observability.

NOT updated (deviation from prompt):

- api/config/security.php — the API CSP is `default-src 'none';
  frame-ancestors 'none'` for JSON responses. Browsers don't enforce
  connect-src on JSON contexts (no document, no fetch origin). Adding
  connect-src would be semantically a no-op and confuse the deny-by-
  default policy.

Regression guard: tests/Feature/Security/CspConnectsToObservabilityTest.
Reads both the dev meta tag and the prod nginx conf directly (the SPA's
CSP is not Laravel-served, so $this->get() can't reach it). Apply-with-
revert verified: stashing both fixes makes both cases fail with a clear
"Refused to connect because it violates the following CSP directive"
hint; popping the stash restores green.

SECURITY_AUDIT.md A13-9 updated with a WS-7 follow-up note documenting
the GlitchTip whitelist as an explicit security control: outgoing
observability traffic restricted to a single known host.

Test count 1549 to 1551. Larastan + Pint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:36:05 +02:00
53ae1a686c docs: WS-7 PR-3 acceptance criteria progress
WS-7 PR-3 commit 4. RFC §6 acceptance criteria 4, 5, 6 now satisfied
by the frontend SDK PR; entries marked  with brief implementation
references.

Updated criterion 4 to reference Crewli's actual token-based portal
paths (/portal/advance/:token, /register/:public_token) instead of the
RFC's speculative /p/* — the contextBinding guard detects via
route.meta.public + route.meta.context which is the canonical Crewli
signal already used by other guards.

Added a "Voortgang (mei 2026)" subsection at the end of §6 mapping
each PR to the acceptance criteria it closed, plus what remains for
PR-4 (live smoke, ARCH-OBSERVABILITY.md, alerting config, retention
config, SECURITY_AUDIT.md update).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:00:54 +02:00
dee140193e test: regression guards for listener registration uniqueness + always-present binary tags
Drie regression-tests die de klasse fouten uit PR-2 nazorg empirisch
voorkomen:

1. test_authenticated_listener_registered_exactly_once
2. test_token_authenticated_listener_registered_exactly_once
3. test_job_processing_tag_listener_registered_exactly_once
   — vangen OBS-8 patroon (auto-discovery + explicit listen samen) plus
   accidentally-removed registrations door toekomstige refactors. Walk
   Event::getRawListeners() en faalt met count != 1 met een duidelijke
   message ("auto-discovery re-enabled? OR explicit Event::listen
   missing?"). Empirisch geverifieerd: zowel duplicate als missing
   registratie wordt gevangen.

4. test_impersonation_active_tag_invariant_on_captured_events
   — RFC §3.6 binary signal invariant op een echte HTTP request flow.
   Vangt regressie waar de baseline-tag-binding verdwijnt.

BACKLOG.md OBS-8 entry toegevoegd en gemarkeerd als Resolved met
verwijzing naar de drie commits van deze sessie + architecturaal
pattern (explicit > implicit voor observability-kritische bindings).

Test count 1545 to 1549. Larastan + Pint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:35:11 +02:00
0379016c7e docs: WS-7 PR-2 follow-up — RFC §3.6 + §3.14 + BACKLOG OBS entries
RFC §3.6 — context tagging tabel volledig vervangen na de PR-2 follow-up
architecturale fixes. Belangrijkste wijzigingen:
- Tag-binding gesplitst in route-scope (BindSentryRouteContext middleware)
  en auth-scope (AuthScopeContextListener op Authenticated event).
- Nieuwe actor_scope tag (organisation/platform/user/anonymous).
- Multi-tenant invariant verfijnd: organisation_id is altijd correct
  gerelateerd aan actor_scope in plaats van "altijd aanwezig". Platform-
  routes zonder org-context worden niet meer gefabriceerd; default
  authenticated user-scope omitt organisation_id (Crewli's User<->Organisation
  is many-to-many, geen reliable single-org hint).
- impersonation.* tags expliciet gedocumenteerd als afkomstig uit
  HandleImpersonation middleware (post-swap), niet uit auth-listener.
- ActorType waarden bijgewerkt na verwijdering van VOLUNTEER case.

RFC §3.14 — status-note toegevoegd dat D-06 indexes al via Spatie's
nullableMorphs default-migratie zijn aangemaakt, met regression-guard
verwijzing.

§6 acceptance criterium 12 markeert D-06 als al voldaan.

BACKLOG.md krijgt vier nieuwe OBS-entries:
- OBS-1: VOLUNTEER actor_type promotion wanneer rol komt
- OBS-4: PHPUnit metadata deprecation cleanup pre-PHPUnit-12
- OBS-6: sentry-laravel install gap awareness + bootstrap test
- OBS-7: custom render handlers report() invariant + coverage

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:05:42 +02:00
932788c643 docs: glitchtip runbook + setup + RFC §3.1 dev amendment
Operational docs for the GlitchTip stack landed in the previous two
commits.

- dev-docs/GLITCHTIP.md: new runbook covering local dev, project
  provisioning + DSN-to-vault flow, production deploy on
  monitoring.hausdesign.nl (DNS, DirectAdmin Let's Encrypt, Apache
  reverse proxy with WS upgrade), backup install + restore drill,
  smoke tests, troubleshooting.
- dev-docs/SETUP.md: services table now includes GlitchTip; new
  docker/glitchtip/.env subsection points at the runbook.
- dev-docs/RFC-WS-7-OBSERVABILITY.md §3.1: amended to record that the
  same compose file drives local dev (Mailpit at bm_mailpit:1025), so
  prod and dev cannot drift.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 08:15:27 +02:00
25888a232b Updated the URL of Glitchtip 2026-05-06 07:42:09 +02:00
1e394879aa docs: RFC-WS-7 observability foundation (GlitchTip)
Two charter amendments from the original WS-7 brief:

- Sentry -> GlitchTip (self-hosted, protocol-compatible). Same
  Sentry SDKs on backend (sentry-laravel) and frontend
  (@sentry/vue), pointed at a self-hosted GlitchTip DSN. Avoids
  Sentry SaaS pricing and keeps event data on infrastructure
  Bert controls.
- Performance monitoring out of scope (errors-only). WS-7
  delivers exception capture + alerting + scrubbing + RBAC
  only. APM/tracing/spans deferred to a later workstream if
  ever needed; pre-launch with no users, the cost/benefit
  doesn't justify it now.

RFC-as-first-commit pattern (per WS-6) so the scope-alignment
document is in main before any infra/code changes land.
2026-05-06 07:32:12 +02:00
1437829501 chore(backlog): close TECH-DOCS-APPS-PORTAL-PURGE
WS-3 PR-C delivered the per-file DELETE/REWRITE/KEEP_AND_PURGE
matrix on all 9 files referenced in the entry, plus the
out-of-scope post-edit-eslint.sh hook fix. Doc-rot removed:
~80 KB of obsolete bootstrap and prompt-template content.

Single SPA, single cookie, single deploy host. WS-3 complete.
2026-05-06 02:14:46 +02:00
d33c119d75 chore(docs): delete obsolete bootstrap and prompt-template docs
Five files removed, all describing project states that no longer
apply post-WS-TOOLING-001:

- .cursor/instructions.md (8.4 KB): Phase 1-4 roadmap with all
  checkboxes empty; Phase 1 has been done for ~6 months. Broken
  'make portal' target. Content overlaps with CLAUDE.md.
- .cursor/ARCHITECTURE.md (18.9 KB): pre-WS-3 framing (dual SPA,
  dual cookies, dual SANCTUM_STATEFUL_DOMAINS) AND pre-Form-Builder
  schema (volunteer_profiles, public_forms with JSON fields). All
  six sections superseded by SCHEMA.md, AUTH_ARCHITECTURE.md,
  design-document.md, API.md, 102_multi_tenancy.mdc.
- dev-docs/MASTER_PROMPT_CC.md (13 KB): 'paste this above every task'
  workflow superseded by auto-loaded CLAUDE.md and structured
  Claude Chat-authored prompts. Stale dual-SPA + pre-Form-Builder
  assumptions throughout.
- dev-docs/MASTER_PROMPT_CURSOR.md (7.5 KB): same workflow obsoletion;
  Cursor is now IDE-only (Claude Code does all implementation).
  .cursor/rules/ system handles IDE-level guidance.
- dev-docs/dev-guide.md (32 KB): bootstrap-from-scratch document
  containing embedded snapshots of pre-Form-Builder CLAUDE.md,
  pre-Form-Builder SCHEMA.md, pre-Form-Builder API.md as
  copy-paste templates. Section 5 prompts pre-WS-TOOLING-001 era.
  Section 6 (agents) overlaps with CLAUDE_CODE_TOOLING.md.

Total: ~80 KB doc-rot removed.

Cross-reference check found four files outside the deleted set
referencing the deleted paths; all updated in the same commit:

- README.md: Documentation table rebuilt around CLAUDE.md +
  dev-docs/* (also dropped stale resources/design/ row pointing
  at a directory that no longer exists, and corrected docs/*
  paths to dev-docs/*)
- dev-docs/CLAUDE_DESKTOP_SETUP.md: dropped MASTER_PROMPT_CC,
  MASTER_PROMPT_CURSOR, dev-guide entries from the
  bewust-verwijderd exclusion list; updated Gerelateerd pointer
  from dev-guide.md -> SETUP.md
- dev-docs/ARCH-CONSOLIDATION-2026-04.md: updated future-distribution
  pointer from dev-guide.md -> SETUP.md (sprint briefing is
  historical so the change is purely doc-hygiene)
- dev-docs/VIBE_CODING_CHECKLIST.md: removed Dev guide row from
  the bestandspaden table

Remaining references in dev-docs/BACKLOG.md (lines 862-869) live
inside the TECH-DOCS-APPS-PORTAL-PURGE entry that closes in the
next commit.

Canonical replacements: dev-docs/SETUP.md (rewritten this PR),
CLAUDE.md, CLAUDE_CODE_TOOLING.md, and the ARCH-*.md series.
2026-05-06 02:14:10 +02:00
bea66a58e6 chore(docs): purge apps/portal mention from CLAUDE_CODE_TOOLING.md
Single-line fix in the hooks reference table. The post-edit-eslint
hook used to scope to apps/app/ or apps/portal/; post-WS-3 there's
only apps/app/.

Code change in the hook script itself lands in the next commit.
2026-05-06 01:51:37 +02:00
5d4132785f chore(docs): rewrite SETUP.md as continue-existing-project guide
Replaces the bootstrap-from-scratch document (Step 2 told readers to
run 'composer create-project laravel/laravel api' on an existing
codebase) with a continue-existing-project guide.

Scope: prerequisites, first-time setup (clone + install + .env + migrate),
daily workflow (three terminals + optional queue worker), env-config
explained, common tasks (test/migrate/route:list/build), documentation
reference linking the dev-docs/ canonical files, troubleshooting.

Drops apps/portal references throughout (single SPA at port 5174).
Drops dual-port SANCTUM_STATEFUL_DOMAINS guidance. Replaces .cursor/
instructions reference with /CLAUDE.md as auto-loaded source of truth.
2026-05-06 01:50:01 +02:00
812cc17460 docs(auth): reflect single-cookie architecture; close A13-3
dev-docs/AUTH_ARCHITECTURE.md (v1.0 → v2.0):
- Title section updated to single-SPA / single-cookie reality
- Client Applications table collapsed to one row
- Cookie Specification table collapsed to one row (crewli_app_token)
- Token Lifecycle / Validation section: Origin-based resolution
  language removed; middleware described as origin-agnostic
- Cross-app isolation paragraph removed (no second app)
- Configuration Reference table marks FRONTEND_PORTAL_URL as legacy,
  pointing at TECH-FRONTEND-URL-CONSOLIDATE
- New §11 "History" preserves the pre-WS-3 dual-cookie context for
  future readers, mentions PR-B2a + PR-B2b roles in the unwind

dev-docs/BACKLOG.md — three new entries:
- TECH-FRONTEND-URL-CONSOLIDATE: refactor email controllers to drop
  per-app URL map (EmailChangeController, PasswordResetController,
  PersonController) — low priority, code-cleanliness only
- TECH-DOCS-APPS-PORTAL-PURGE: sweep apps/portal references from
  briefing/tooling docs (.cursor/, MASTER_PROMPT_*, SETUP, dev-guide,
  CLAUDE_CODE_TOOLING) — single chore(docs) PR, low priority
- OPS — DNS retirement of portal.crewli.app — operational task,
  deferred until traffic monitoring confirms zero usage

dev-docs/SECURITY_AUDIT.md:
- A13-1 narrative actualised: pre-WS-3 dual-cookie context kept as
  history, status flipped to RESOLVED (the localStorage→httpOnly
  migration shipped earlier in the consolidation arc)
- A13-3: status flipped to RESOLVED by WS-3 PR-B2b; description
  rewritten to reflect the new postLoginRedirect.ts validator and
  the 16 spec coverage
- Priority remediation table item 8 strikes through A13-3

Backend test suite: 1487 passed (unchanged from Commit 2 baseline).
Frontend: 223 passed (unchanged from Commit 1 baseline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 00:29:26 +02:00
538072241e docs(backlog): WS-TOOLING-001 done + 3 follow-up tech items 2026-05-06 00:08:09 +02:00
b1773ea1f3 docs(claude): document rm -rf rule in hooks reference table 2026-05-05 23:56:21 +02:00
735ba2c8d9 docs: add CLAUDE_CODE_TOOLING.md and cross-reference from CLAUDE.md
Documents the deterministic guard-rail layer: hooks reference,
crewli-reviewer subagent usage, three slash commands, how to test
hooks, how to disable temporarily, and the binding design principle
(settings/hooks deterministic, CLAUDE.md advisory — never duplicate).
2026-05-05 23:25:03 +02:00
68f1e6f80c Merge pull request 'WS-3 PR-B2a: auth + routing consolidation (single SPA, dual axios, context-aware guards)' (#5) from feat/ws-3-pr-b2a-auth-routing-consolidation into main
Reviewed-on: #5
2026-05-05 22:43:52 +02:00
145d0cbdad docs(backlog): add ARCH-API-RESPONSE-VALIDATION workstream entry
Workstream-sized item geborgt voor uniforme typed + runtime-validated
contracts op de API-grens (backend PHP Enums, frontend Zod schemas,
codegen TS types). Scope, sequentie (post-PR-C/WS-7, pre-RFC-FORM-BUILDER-UI),
en open beslissingen vastgelegd. Verwijst naar dev-docs/ARCH-API-VALIDATION.md
skeleton voor architectuur-detail.

Voorkomt dat S3b technische schuld stapelt — landt vóór RFC-FORM-BUILDER-UI
zodat nieuwe composables vanaf dag één het gevalideerde patroon consumeren.
2026-05-05 22:32:05 +02:00
babbbd97cb docs(arch): add ARCH-API-VALIDATION.md skeleton — uniform API response validation workstream 2026-05-05 22:17:27 +02:00
a2760ffd64 feat(auth): add contexts + platform.is_super_admin to /auth/me, factory role-category states
Additive enrichment to MeResource — existing fields untouched, MeTest stays green.
New fields:
- contexts.available: list<'portal'|'organizer'> derived from Person + Organisation memberships
- contexts.default: precedence super_admin > organizer > portal > fallback portal
- platform.is_super_admin: bool promoted from app_roles
- organisations[].roles: 1-element array form alongside the legacy scalar role,
  forward-compatible for the multi-role pivot work tracked in TECH-PIVOT-ROLES-MULTI

UserFactory gains volunteer(), orgAdmin(), volunteerAndOrganizer(), superAdmin()
state methods — codified role categories for reuse across future workstreams.

Adds forbidden.vue placeholder (PublicLayout) for the context-failure landing in
the upcoming guard rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 21:15:10 +02:00
d1503ceadf docs(vuexy): update VUEXY_COMPONENTS.md for post-PR-B1 single-SPA reality
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:33:33 +02:00
a4281df021 docs(arch): add ARCH-BINDINGS.md — canonical reference for FormBindingApplicator pipeline (WS-8a) 2026-05-05 20:22:11 +02:00