§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>
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>
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>
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>
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>
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.
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>
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.
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>
Records the naming-vs-coverage gap surfaced during WS-6 closure
verification: ARCH-FORM-BUILDER §31 references five integration
contract tests by name that don't exist under those filenames in
api/tests/Feature/FormBuilder/Integration/. Coverage may be intact
under different filenames; only the §31 naming index is stale.
Low priority — defer to whoever next touches FormBuilder
integration tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the closed TECH-AXIOS-STORE-COUPLING entry from BACKLOG.md
(the structural decoupling landed in 53f6a7b + 26a92b3). The
git-history search `git log --grep=TECH-AXIOS-STORE-COUPLING`
remains the durable closure record, per the backlog hygiene
convention.
Adds a follow-up entry TECH-AXIOS-INTERCEPTOR-TESTS that captures
all four acceptance scenarios (X-Organisation-Id header
injection, 401 auth-fail flow, 403+impersonation_ended revocation
flow, 4xx/5xx error toast). Phase A audit found that none of
these is tested today; the refactor is gedragsneutraal so no
regression was introduced, but the gap is real and should not
silently outlive the refactor that made it visible. Priority
medium per Bert's Phase B sign-off.
Appends the debt-closed sentence to the Sessie 1c entry in
ARCH-CONSOLIDATION-2026-04.md, citing commit 53f6a7b.
Co-Authored-By: Claude <noreply@anthropic.com>
Triggered by the typed-router.d.ts regeneration in 3198698. Documents
three approaches (lefthook pre-commit, gitignore+postinstall, CI-check)
with their trade-offs. Defers selection to implementation time;
recommends bundling with the next pages-tree refactor (likely WS-3 PR-B).
Co-Authored-By: Claude <noreply@anthropic.com>
- TECH-VSCODE-STALE-ADMIN-ENTRY: closed in b9f8f558d1
- TECH-DELETE-DEAD-VIEWS: closed in bdbd5b0335
Both items shipped; references preserved in git history.
Co-Authored-By: Claude <noreply@anthropic.com>
- TECH-PORTAL-ESLINT-DEPS: audit apps/portal/package.json on the
same missing-direct-deps pattern uncovered in apps/app (commit
4369806). Cursor's strict ESLint resolution will hit identical
issues for portal users until fixed.
- TECH-ESLINT-V9-MIGRATION: ESLint v8.57.1 is EOL since end-2024.
Migration to v9 + flat config + modern @antfu/eslint-config is a
dedicated 1-2 day workstream.
- TECH-VSCODE-STALE-ADMIN-ENTRY: .vscode/settings.json still
references apps/admin in eslint.workingDirectories; removed in
April 2026. Trivial cleanup.
Two new BACKLOG entries capture the deliberate v1 deferrals:
- ARTIST-ADV-BINDING-MODEL — design how artist_advance form data
relates to Artist + AdvanceSection entities (when, if ever, an
Eloquent Artist class is needed, and whether bindings are even
the right abstraction for OUTPUT-shaped advance forms).
- FORM-BINDING-JSON-PATH — extend binding registry to support
JSON-path attributes (custom_fields.dietary_preferences etc).
For v1 the recommendation is TAG_PICKER + tag_categories config.
ARCH-BINDINGS.md gets an appendix explaining the v1 scope decisions
explicitly: why 'artist' has no registry entries (model class
absent + advance forms are OUTPUT-shaped, not provisioning-shaped),
why JSON-path attributes are out of scope (v1 is column-level only),
and how BindingTypeRegistryConsistencyTest prevents future drift.
RFC-WS-6.md → v1.2 with a §3 Q9 addendum tracking the registry
alignment + the 3 renames, 5 removals, and 1 new column landed in
this branch.
Refs: WS-6 sessie 3a binding-target drift audit, sessie 3a.5 cleanup
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reflects the FormFieldChildTableMorphScope extraction landed in the
previous commit:
- ARCH-FORM-BUILDER.md v1.9 — five locations updated:
§6.7 (Relational binding table) — added forward reference
sentence after the FormFieldBindingScope escape-hatch line
(WS-5a was the first scope; previously had no deferral note
because nothing existed yet to defer)
§17.4.2 (Relational table form_field_validation_rules) —
"deferred to WS-5d per addendum Q3" replaced with marker-
subclass forward reference
§17.5.3 (Service, scope, cascade — config) — same replacement
§17.6.1 (Field options rationale) — "unblocks the deliberate
follow-up" replaced with completion-confirmation
§17.6.3 (Service / scope / cascade — option) — "deferred to a
follow-up work package" replaced with marker-subclass forward
reference + Phase A diff verification result
Version metadata + changelog updated; v1.8 prose preserved in the
Previous-versions block.
- ARCH-CONSOLIDATION-ADDENDUM-2026-04-24.md — new
"Uitvoering — base scope-class extractie (2026-04-25)" section
inserted after the WS-5d Uitvoering, documenting the Phase A
diff-verification, marker-subclass approach, private→protected
YAGNI policy, the inline-FQN → use-statements stylistic refinement,
static-analysis impact (Larastan baseline clean, Rector
357 → 355), and net-diff figures.
- BACKLOG.md — FORM-BUILDER-MORPH-SCOPE-BASE-CLASS item closed
via strikethrough header + "Status: closed 2026-04-25" annotation
(matches the TECH-TS-PORTAL-TSC closure convention from earlier
this week).
- SCHEMA.md — three stale "deferred" claims updated to reflect the
completed extraction:
header v2.6 changelog mention rewritten to point at the now-
landed FormFieldChildTableMorphScope
form_field_validation_rules table-section global-scope note
replaced with marker-subclass forward reference
form_field_options table-section global-scope note same
replacement
Schema version NOT bumped — no actual schema change.
The two other scope mentions (form_field_bindings,
form_field_configs) made no deferral claims and remain accurate.
Note: the work package's prose listed "§6.7 / §17.4.3 / §17.5.3 /
§17.6.3" as deferral-note locations. The actual locations were
§17.4.2 (not §17.4.3), §17.5.3, §17.6.1 (not just §17.6.3), and
§17.6.3 — §6.7 had no deferral note (WS-5a was the first scope,
nothing to defer yet). All five spots updated in line with the work
package's intent.
WS-5 family fully complete: no open follow-up items remain under the
"delete > adapt" discipline of the WS-5 refactor.
Tests: 1208 passed (3260 assertions). No code changes in this commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings apps/portal from 729 vue-tsc errors (≈22 own-code, of which
18 were TS2339 downstream of tiptap; ≈707 in node_modules/@tiptap/)
to zero. Tiptap fix-route: Option A — patch upgrade @tiptap/* from
2.27.1 to 2.27.2 to fix tiptap's dist/index.d.ts re-export paths.
Sprint commits (this work package, 3 total):
- f7bb864 fix(portal-deps): upgrade @tiptap/* 2.27.1 → 2.27.2
to fix dist resolution (cleared 707 + 18 errors)
- a7ccd2b fix(portal-types): clear residual long-tail tsc errors
(cleared the 4 tiptap-independent stragglers:
vite.config.ts componentName param,
LayoutConfig.title Lowercase<string> over-constraint,
@iconify/types missing dev-dep, casl.ts meta string cast)
- this commit: close BACKLOG entry; correct the misleading "+4 in
tiptap" framing in the original entry (was the
ts-reset delta, not the absolute pre-existing count
of ~707); seed TECH-PORTAL-TSC-CI-GATE follow-up.
apps/portal `pnpm exec vue-tsc --noEmit` exits clean.
Vitest: 113/113 passing. Build: 8.52s, succeeded.
Pre-commit hook gate not added — the project has no husky/lefthook/
simple-git-hooks setup. Captured as TECH-PORTAL-TSC-CI-GATE follow-
up; without that gate the zero state has no enforcement and can
drift back. Should land before S3b organizer UI work to keep the
"new code introduces no new errors" discipline mechanically
enforceable.
S3b form-builder organizer UI can now land on top of a verified
TypeScript baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both items currently sit at default priority. Foundation-tooling
commit 3 (ts-reset install) surfaced them but didn't constrain
when they need to close.
Adds explicit S3b-trigger rationale: launching the form-builder
organizer UI in apps/app on top of:
- 22 unverified pre-existing TypeScript errors in apps/portal,
AND
- zero Vitest setup in apps/app
is asymmetric quality, exactly the discipline gap that bites in
post-launch debugging. Both items now flagged "high before S3b
lands" with concrete close-criteria.
TECH-TS-PORTAL-TSC additionally clarifies tiptap node_modules
handling. Phase A check confirmed `skipLibCheck: true` is already
set in both SPAs' single tsconfig.json (no `tsconfig.app.json` /
`tsconfig.node.json` variants exist). Despite that, the 4 tiptap
errors persist because tiptap ships uncompiled `.ts` source files
in `node_modules/.../@tiptap/core/src/`, not `.d.ts` — and
`skipLibCheck` only suppresses checking of `.d.ts` files. Real
fix paths are upstream `@tiptap/*` upgrade (newer majors may ship
`.d.ts` only) or a focused `exclude` glob; flipping skipLibCheck
is a non-fix because it is already on.
TECH-APP-VITEST adds a 6-step setup outline scoped to "harness
exists + one test passes", explicitly excluding comprehensive
test-writing for existing apps/app code. `useImpersonationStore.ts`
called out as a natural early target — it has no runtime test
today and the pending TECH-TS-IMPERSONATION shape-validation work
benefits from coverage.
CLAUDE.md quality-gates list adds a Vitest entry that surfaces
the apps/portal / apps/app asymmetry, with a pointer to
TECH-APP-VITEST.
No code changes. Documentation only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Installs @total-typescript/ts-reset 0.6.1 as a dev-dependency in
apps/portal/ and apps/app/. Patches TypeScript's loosest default
types: Array.filter(Boolean) returns non-nullable, JSON.parse
returns unknown, fetch().json() returns unknown, Map.get() strict,
etc.
Configuration: src/reset.d.ts in each SPA imports the reset. Both
tsconfig.json files already include ./src/**/* so the .d.ts is
picked up automatically — no tsconfig edits needed.
Issues surfaced during install:
- apps/app — 0 pre-install tsc errors in own code; install
surfaced 2 errors in src/stores/useImpersonationStore.ts
(both from JSON.parse on sessionStorage content returning
unknown instead of any). Fixed inline at lines 19 + 123 via
`as ImpersonationState` casts that make the existing
trust-in-sessionStorage explicit. Backlog entry
TECH-TS-IMPERSONATION tracks proper runtime shape validation.
- apps/portal — 22 pre-existing tsc errors in own code (mostly
tiptap editor components — tracked as TECH-TS-PORTAL-TSC,
unrelated to ts-reset). Zero new errors in portal's own code.
4 additional errors surfaced in tiptap's uncompiled node_modules
.ts sources (third-party); left as-is.
Neither SPA achieves `tsc --noEmit` clean today — pre-existing
state unrelated to this work package. Build + vitest are the
actual working gates and both remain green:
- apps/portal: vitest 113/113 passing; production build succeeds
- apps/app: (no vitest setup — tracked as TECH-APP-VITEST);
production build succeeds
Documentation: /dev-docs/FRONTEND-TOOLING.md added; CLAUDE.md
quality-gates updated.
Backlog: TECH-TS-IMPERSONATION (runtime validation of stored
impersonation state), TECH-TS-PORTAL-TSC (pre-existing portal tsc
errors), TECH-APP-VITEST (Vitest coverage for apps/app).
No production behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final WS-5d cleanup. The JSON columns that have been unread since
commit 3 are now physically dropped on both source tables. Their
canonical rich-shape lives in form_field_options, accessed
exclusively through the morphMany relation.
Defensive sweep: any lingering translations.{locale}.options key in
either source table's translations bag is stripped. Commit 2's
backfill should already have done so exhaustively; this is
belt-and-braces.
Rollback re-creates the columns as nullable JSON but leaves them
empty. Pair with commit 2's rollback to restore the pre-WS-5d data
shape on every owner row.
The commit-3 getOptionsAttribute accessor-bridge on FormField +
FormFieldLibrary is removed — Eloquent's getAttribute() resolution
now naturally falls through to the morphMany relation since there's
no underlying column to shadow it. New regression test
FormFieldOptionsAccessTest asserts $field->options resolves to an
Eloquent Collection of FormFieldOption instances and lazy-loads in
exactly 2 queries (1 parent + 1 lazy-load options) on a fresh fetch
without with() preload. Same trio for FormFieldLibrary.
Migration step-count tests in WS-5a/b/c bumped by 1 to account for
the new drop_form_field_options_json_columns migration on the
rollback stack.
Documentation:
- SCHEMA.md v2.6: form_field_options table documented; options row
removed from form_fields and form_field_library; morphMany
relations updated; cross-references to ARCH-FORM-BUILDER §17.6
and addendum §Q3 WS-5d Uitvoering added on both source-table
docblocks.
- ARCH-FORM-BUILDER.md v1.8: new §17.6 "Field options (relational)"
mirrors the §17.4 / §17.5 relational-sibling structure with
sub-sections 17.6.1 rationale, 17.6.2 table + catalogue, 17.6.3
service / scope / cascade / activity log, 17.6.4 snapshot
embedding, 17.6.5 external API contract. Existing Webhooks
section renumbered from §17.6 to §17.7.
- ARCH-CONSOLIDATION-ADDENDUM-2026-04-24.md: "Uitvoering — WS-5d
(2026-04-27)" section added. Eight paragraphs covering the
snapshot atomic rewrite, strict-fail backfill dispatch, dual
activity-log emit, four-sibling base-class extraction warrant,
commit 0 dead-code precondition, the temporary getOptionsAttribute
accessor-bridge pattern (with reusability note for future
JSON→relational refactors), the dev-seeder vergoedingstype RADIO
normalisation (drift correction explicitly distinguished from the
parallel apps/app RegistrationFieldTemplate description domain),
and the WS-5 family completion note.
- BACKLOG.md: FORM-BUILDER-LIBRARY-AUDIT-LOG entry extended to four
services (adds library.options_replaced); new
FORM-BUILDER-MORPH-SCOPE-BASE-CLASS entry added as the WS-5d
follow-up now that all four concrete morph-scope siblings exist.
Tests: 1193 → 1208 green (+15 across commits 3+4+5; this commit alone:
+2 from the regression test).
This completes the WS-5 family.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-flight audit verified the implementation was already in place,
so this commit is test-only (as the task prompt allowed):
- api/database/migrations/2026_04_08_220000_create_persons_table.php:27
already carries $table->softDeletes().
- api/app/Models/Person.php lines 18 + 24 already use the SoftDeletes trait.
No production code change required.
tests/Feature/Person/PersonSoftDeleteTest.php pins the documented
behaviour so WS-6 (FormBindingApplicator + ARTIST_ADVANCE /
EVENT_REGISTRATION workflows) can rely on it without a second
verification pass:
- delete() sets deleted_at and excludes the row from default queries
- Person::withTrashed()->find($id) returns the soft-deleted row
- Person::onlyTrashed()->count() reports accurately
- restore() clears deleted_at
- forceDelete() removes the row permanently
PersonPolicy was spot-checked alongside the audit; existing view/update/
delete methods do not invoke withTrashed() on controller resolution.
That's acceptable today — no caller relies on editing a trashed Person —
so AUTH_ARCHITECTURE.md is left unchanged. If a restore-workflow lands
in a future sprint, the controller binding will need to switch to
->withTrashed() and the behaviour deserves a dedicated doc paragraph
then.
Minor path note: the task prompt specified
tests/Feature/Persons/PersonSoftDeleteTest.php (plural), but the
existing convention in this repo is tests/Feature/Person/ (singular).
Matched the existing directory rather than introducing a singular/plural
split.
Also carries the BACKLOG DOC-04 entry Bert asked for during WS-4 review:
scripts/install-claude-sync-hooks.sh belongs in SETUP.md / onboarding
so new clones don't miss the post-commit sync hook.
5 tests / 10 new assertions. Full suite: 1005 passed (2716 assertions).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds ARCH-CONSOLIDATION-2026-04.md as the authoritative reference for the
upcoming 8-workstream architecture consolidation sprint: purpose registry
cleanup, ULID consistency, JSON column split, binding infrastructure,
FormBindingApplicator, single-SPA consolidation to crewli.app, observability
foundation, docs consolidation.
Sprint scope, leading principles, workstream ordering, and chat-transition
protocol are captured in the document. Follow-up chats will start from this
document as primary context.
Also updates BACKLOG.md with an active-sprint marker pointing to the briefing.
Documents the technical debt introduced when the organizer API composables
(useSections, useFormSchemas) adopted a minimal PaginatedResponse shape
that discards Laravel's links and meta blocks. PR-b2 will surface the
first UI consumer that needs pagination controls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves TECH-07. Copies the four validators actually used
(requiredValidator, emailValidator, urlValidator, regexValidator) from
@core/utils/validators into packages/form-schema/src/utils/validators.ts
as pure boolean functions. Vuexy template copies in apps/*/src/@core/
remain for non-form UI use. Package is now genuinely standalone —
grep -rn "@core/" packages/form-schema/ returns zero matches.
Also corrects two documentation inconsistencies from commit 42dd626e:
dev-guide heading translated to Dutch for style consistency, and the
BACKLOG entry renumbered from TECH-DEBT-01 to TECH-07 to match the
flat numbering in the Technische schuld section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the "share schema, not UI" principle in dev-guide.md so the
boundary stays intact in future work. Logs TECH-DEBT-01 for the
@core/utils/validators transitive dependency discovered during PR-a.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- TECH-06 — ESLint config ontbreekt in apps/portal (pendant van TECH-05).
- DOC-02 — VitePress docs:build faalt op missing image in
/docs/volunteer/je-aanmelden-via-een-link.md.
- DOC-03 — Formulieren sidebar story is incompleet; nog geen
publicatieflow, inzendingen-overzicht, templates, webhooks,
conditionele logica.
- FORM-09 — TriggerPersonIdentityMatchOnFormSubmit ShouldQueue
herzien: async queue-dispatch levert null bij submit-response;
eager state + lazy resolution patroon invoeren nu de refactor
nog klein is (voor FORM-05 landt).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add VitePress pages for AVAILABILITY_PICKER and SECTION_PRIORITY
and a TAG_PICKER configuration note. Wire them into the organisator
sidebar under a new Formulieren section alongside the existing
"Wat is een formulier" page.
- BACKLOG.md: nuance FORM-05 — the stub-shaped behaviour for public
event_registration submissions is already shipping via the existing
TriggerPersonIdentityMatchOnFormSubmit listener (writes 'pending').
The real work (PersonIdentityService::detectMatchesByValues + an
extra branch in resolveStatus) is what remains. Added a done entry
for S3a PR 2 to the Opgeloste items list.
- API.md: add VALIDATION_FAILED to the public-form error code table
and document the SECTION_PRIORITY shape error messages (Dutch copy
served under errors."values.{slug}").
- COPY_CATALOGUE.md: new S3a PR 2 section capturing the seeder
help_text, the IdentityMatchBanner copy (clearly marking the
backend message as authoritative), all empty/error state copy for
the three new components, and the SECTION_PRIORITY shape error
strings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
S2c Phase 8.
- API.md: new **Form Builder (Public)** section documenting all 6
public endpoints (GET schema + time-slots + sections; POST draft,
PUT save, POST submit) with request/response examples, error codes,
and the identity_match / schema_drift contracts. No PII-echo noted
explicitly.
- SCHEMA.md bumped to v2.1:
- changelog entry for S2c.
- form_submissions table gains schema_version_at_open +
identity_match_status columns; UNIQUE (form_schema_id,
idempotency_key) replaces the composite index; a new composite
index (form_schema_id, identity_match_status) landed for the
organiser "pending-match" dashboard.
- ARCH-FORM-BUILDER.md bumped to v1.3 with new §10.4 "Public
submission lifecycle — draft/save/submit split" documenting the
three-endpoint contract, idempotency, schema-drift detection,
access rules, the standardised error envelope, and the dependency
data sub-endpoints.
- BACKLOG.md adds:
- FORM-04 (grace_days configurable — current implementation still
uses the hard-coded 7-day window)
- DOC-01 (Scramble / OpenAPI generator for API.md to reduce the
docs-drift effort going forward).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 7 of S2b.
- API.md: "Form Builder" section rewritten with every new route
(schemas / fields / submissions / values / delegations / templates /
field library / webhooks / filter registry / public token flow).
Calls out §22.8 typed-confirmation deletes, §6.5 binding-change guard,
§9 signature hash on submit, §7.4–§7.5 FilterQueryBuilder contract,
and that FormSubmissionSubmitted is the trigger for the §31.10
TAG_PICKER sync listener.
- BACKLOG.md: FORM-02 marked done with the shipped artefacts and the
deferred §31.9 contract tests spelled out.
- ARCH-FORM-BUILDER.md §31.10 already rewrote authoritatively in Phase 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>