Add blank line between the new pointer blockquote and the **Aligned to:**
paragraph so the blockquote closes cleanly across markdown renderers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All corrections audited against the codebase:
- §7.4 useWorkspaceStore ghost removed (computed over auth/org stores)
- §12 portal /portal/* verified in repo; observability is meta-based,
/api/v1/p/* is separate backend layer — no cross-doc conflict
- §3 getRouteName v2- name-prefix convention (route-name collision)
- §4 theme parallel-mode AD + useRightDrawer in useShellUiStore
- §8/§9 DraggableBlock is foundation, not Tier-4
- §3 single ESLint enforcement for definePage meta-key
- §8 StatusTag severity map; §14 brace-glob fallback; §13 CT/Storybook
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brainstorming outcome: pivot the PrimeVue redesign to use crewli-starter
as the design source of truth, parallel /v2/ routes, PrimeVue-first
fidelity, page-by-page cutover. Supersedes F4a-F4d of
RFC-WS-FRONTEND-PRIMEVUE.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three RFC drift corrections discovered during F3 implementation:
1. AD-5 icon rendering: corrected from "<i :class='i-tabler-X'>"
utility-class pattern (which would require UnoCSS, not installed)
to "@iconify/vue's <Icon> component with name='tabler-X' prop"
(existing Crewli pattern producing real SVG output). The thin wrapper
shipped in F3 B6 as apps/app/src/components/Icon.vue accordingly.
2. AD-2 theme architecture: corrected package reference from
@primevue/themes@^4.5 (deprecated by PrimeFaces) to
@primeuix/themes@^2 (the path now prescribed by PrimeVue 4's
official install docs at primevue.org/vite/). Same maintainers,
same API surface (definePreset, Aura preset, semantic tokens).
F3 commit B1 already uses the corrected package.
3. Appendix B Aura theme token plan: updated import-path examples to
@primeuix/themes and @primeuix/themes/aura accordingly.
Also updated:
- §6 F3 deliverables list: dependency line now reads @primeuix/themes@^2
with a footnote linking to the B1 rationale.
- Appendix C Version Pinning Policy: separated @primeuix/themes from
the primevue/^primevue/forms lockstep pin (independent release cadence).
- dev-docs/PRIMEVUE_COMPONENTS.md §3 (Data display): VIcon row updated
to <Icon name="tabler-..." />; surrounding migration-spirit paragraph
rewritten; §10 external-resources link relabeled to @primeuix/themes.
These are RFC drift corrections — the implementation in F3 (commits
B1, B2, B6 of this sprint) already uses the corrected packages and
import paths. This commit aligns the spec with reality so future
contributors don't reach for the deprecated/inaccurate documentation.
.claude-sync/ regenerates automatically post-commit via lefthook.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lefthook v2 runs `git lfs pre-push` internally for pre-push hooks (per
docs/usage/features/git-lfs.md; confirmed in internal/run/controller/
lfs.go where the internal handler invokes `git lfs pre-push <remote>
<url>` with a buffered `cachedStdin`). Our manual `git-lfs:` command
in lefthook.yml was a second invocation against the same remote; the
duplicate is directly visible in `LEFTHOOK_VERBOSE=1` output as
`[git-lfs] executing hook` (internal) followed by `[lefthook] run:
git lfs pre-push` (manual).
The previous fix attempt (piped: true, commit 1b06804) was based on a
wrong understanding of `piped`'s semantics — `piped` controls
fail-fast behavior, not stdin routing or sequencing. Default lefthook
behavior is already sequential per docs/configuration/parallel.md.
That "fix" was placebo; incident 2 (F2 push, zero LFS objects, commit
99eedb6) proved it.
Phase A investigation: documentary + source confirmation that lefthook
owns the LFS pre-push call. Phase B sandbox test against a filesystem
remote confirmed the duplicate execution in logs but did NOT reproduce
the production hang — likely because the duplicate manual call against
a local remote has no LFS server to interact with. A network-y remote
(Gitea over SSH/HTTPS) appears to be part of the trigger. Two
mechanisms remain plausible (H1: PTY-stdin without EOF in
`while read` loop per docs/configuration/use_stdin.md; H4: server-side
LFS interaction on the duplicate call). Both are eliminated by the
same fix: remove the manual command. LFS uploads continue to work via
lefthook's internal handler (verified in sandbox post-fix).
Regression coverage: scripts/test-lefthook-pre-push.sh asserts exactly
one internal LFS invocation, zero manual ones, and `Uploading LFS
objects: 100%` present, against a disposable sandbox.
See dev-docs/ADR-LEFTHOOK-LFS-INTEGRATION.md for full context, both
misconceptions to prevent regression, and the alternative-scenarios
playbook if Phase E ever regresses.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Vuexy/Vuetify component reference is superseded by PRIMEVUE_COMPONENTS.md
per RFC-WS-FRONTEND-PRIMEVUE. Stub forwards readers to the new doc and
provides the explicit pre-F2 SHA (1c449ff620)
for retrieving the original 777-line content during F4a–F4c on
un-migrated surfaces.
File deleted entirely in F6 cleanup. Stub-not-delete decision per
2026-05-10 project chat (Bert): explicit forwarding marker beats
git-history archaeology while parallel-mode is in force.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Foundation document for F2 of RFC-WS-FRONTEND-PRIMEVUE. Encodes
Crewli-specific conventions for the Vuetify→PrimeVue migration:
- Component mapping by category (form / layout / data display /
feedback / navigation / overlays), each with a paragraph on
migration spirit; cross-references PrimeVue docs rather than
duplicating reference material
- Aura theme + Crewli teal primary token plan (full token list in
RFC Appendix B; F3 implements)
- Canonical forms pattern: @primevue/forms + Zod resolver +
<FormField> wrapper (full API spec lives in RFC Appendix A —
cross-referenced, not duplicated)
- DataTable conventions: lazy / virtual / column-template, with a
slot translation cheat sheet from VDataTable
- pt API + Tailwind v4 + Aura tokens decision matrix
- Migration phase guidance (surface-level consistency rule, no
back-porting, F6 cliff)
- VIcon stays Iconify-Tabler per RFC AD-5; PrimeIcons not installed
Length: 385 lines. F4 sub-packages will extend §3 as surfaces migrate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Marks all three sprint backlog entries Resolved with sprint commit
references and documented deviations:
- TEST-INFRA-001 (b8d18e6, 82af117, f6509d9, 2dfb1e8) — Playwright
foundation operational locally. CI deferred.
- TEST-CONTRACT-001 (2dfb1e8) — 409 conflict shape verified against
real Laravel. Single-context replay instead of two-browser
concurrent edit; UI rollback assertion deferred to F4.
- TEST-VISUAL-001 (f6509d9) — 5 composite baselines from canonical
prototype. Composite-over-isolated rationale: prototype DOM lacks
data-* attributes; isolated artist-name locators would rot. F4
adds isolated baselines using stable data-test-id.
Opens TEST-INFRA-002 for the deferred CI work: Gitea/GitHub Actions
decision, runner image, caching, screenshot-diff artifacts, label-
gated nightly e2e. No deadline; surfaces when first review cycle
feels drift.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
B5 of TEST-INFRA-001 (RFC-WS-FRONTEND-PRIMEVUE Amendment A-1).
- Add dev-docs/ARCH-TESTING.md (~13 KB):
§1 Five-tier pyramid (Unit / Component / Integration / Visual /
E2E) with environment, cost, and purpose per tier
§2 Decision tree — pick by what is being verified, not by speed
§3 Mock-vs-real-backend rules + the self-confirming-bias anti-
pattern that motivated TEST-CONTRACT-001
§4 Visual baseline workflow including the composite-over-isolated
strategy used in B3
§5 CI strategy stub — deferred to TEST-INFRA-002
§6 Conventions + 5 anti-patterns
§7 Vuetify-during-PrimeVue-migration: explicit doc that the
Vuetify plugin in playwright/index.ts is INTENTIONAL TEMPORARY
STATE replaced in F3 by PrimeVue. Forbids the "abstract the UI
framework provider" deferred-cost trap.
§8 Host setup — Node, pnpm, Chromium, Git LFS, MySQL 8, PHP, .env;
known risks (unpkg.com flakiness, shared crewli_test DB)
§9 Deferred work cross-references to BACKLOG entries
- Update CLAUDE.md ### Testing section to reference ARCH-TESTING.md
- Add ARCH-TESTING.md to .claude-sync.conf so the dev-docs sync
pipeline picks it up; sync script run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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)
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>
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>
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>
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>
§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>
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>
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>
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>
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>
§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>
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>
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>
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>
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 #1123a5696).
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>
§1 Status: add Implementation status line citing D1 (PR #10c6f4d1b)
and D2 (PR #1123a5696), 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>